UNPKG

9.1 kBJavaScriptView Raw
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14'use strict';
15
16const NS = 'org.accordproject.commonmark';
17const NS_CICERO = 'org.accordproject.ciceromark';
18/**
19 * Removes nodes if they are an empty paragraph
20 * @param {*} input - the current result of slateToCiceroMarkDom
21 * @returns {*} the final result of slateToCiceroMarkDom
22 */
23
24const removeEmptyParagraphs = input => {
25 let nodesWithoutBlankParagraphs = [];
26 input.nodes.forEach(node => {
27 if (node.$class === 'org.accordproject.commonmark.Paragraph' && node.nodes.length === 1 && node.nodes[0].$class === 'org.accordproject.commonmark.Text' && node.nodes[0].text === '') {
28 return;
29 }
30
31 nodesWithoutBlankParagraphs.push(node);
32 });
33 input.nodes = nodesWithoutBlankParagraphs;
34 return input;
35};
36/**
37 * Gather the text for the node
38 * @param {*} input - the current slate node
39 * @returns {string} the text contained in the slate node
40 */
41
42
43const getText = input => {
44 let result = '';
45
46 if (input.text) {
47 result += input.text;
48 }
49
50 if (input.nodes) {
51 input.nodes.forEach(node => {
52 result += getText(node);
53 });
54 }
55
56 return result;
57};
58/**
59 * Converts a Slate document node to CiceroMark DOM (as JSON)
60 * @param {*} document the Slate document node
61 * @returns {*} the CiceroMark DOM as a Concerto object
62 */
63
64
65function slateToCiceroMarkDom(document) {
66 const result = {
67 $class: 'org.accordproject.commonmark.Document',
68 xmlns: 'http://commonmark.org/xml/1.0',
69 nodes: []
70 }; // convert the value to a plain object
71
72 const json = document;
73
74 _recursive(result, json.nodes);
75
76 return removeEmptyParagraphs(result);
77}
78/**
79 * Converts an array of Slate nodes, pushing them into the parent
80 * @param {*} parent the parent CiceroMark DOM node
81 * @param {*} nodes an array of Slate nodes
82 */
83
84
85function _recursive(parent, nodes) {
86 nodes.forEach((node, index) => {
87 let result = null;
88
89 switch (node.object) {
90 case 'text':
91 result = handleText(node);
92 break;
93
94 default:
95 switch (node.type) {
96 case 'clause':
97 // console.log(JSON.stringify(node, null, 4));
98 result = {
99 $class: "".concat(NS_CICERO, ".Clause"),
100 clauseid: node.data.clauseid,
101 src: node.data.src,
102 nodes: []
103 };
104 break;
105
106 case 'variable':
107 case 'conditional':
108 case 'computed':
109 result = handleVariable(node);
110 break;
111
112 case 'paragraph':
113 result = {
114 $class: "".concat(NS, ".Paragraph"),
115 nodes: []
116 };
117 break;
118
119 case 'softbreak':
120 result = {
121 $class: "".concat(NS, ".Softbreak")
122 };
123 break;
124
125 case 'linebreak':
126 result = {
127 $class: "".concat(NS, ".Linebreak")
128 };
129 break;
130
131 case 'horizontal_rule':
132 result = {
133 $class: "".concat(NS, ".ThematicBreak")
134 };
135 break;
136
137 case 'heading_one':
138 result = {
139 $class: "".concat(NS, ".Heading"),
140 level: '1',
141 nodes: []
142 };
143 break;
144
145 case 'heading_two':
146 result = {
147 $class: "".concat(NS, ".Heading"),
148 level: '2',
149 nodes: []
150 };
151 break;
152
153 case 'heading_three':
154 result = {
155 $class: "".concat(NS, ".Heading"),
156 level: '3',
157 nodes: []
158 };
159 break;
160
161 case 'heading_four':
162 result = {
163 $class: "".concat(NS, ".Heading"),
164 level: '4',
165 nodes: []
166 };
167 break;
168
169 case 'heading_five':
170 result = {
171 $class: "".concat(NS, ".Heading"),
172 level: '5',
173 nodes: []
174 };
175 break;
176
177 case 'heading_six':
178 result = {
179 $class: "".concat(NS, ".Heading"),
180 level: '6',
181 nodes: []
182 };
183 break;
184
185 case 'block_quote':
186 result = {
187 $class: "".concat(NS, ".BlockQuote"),
188 nodes: []
189 };
190 break;
191
192 case 'code_block':
193 result = {
194 $class: "".concat(NS, ".CodeBlock"),
195 text: getText(node)
196 };
197 break;
198
199 case 'html_block':
200 result = {
201 $class: "".concat(NS, ".HtmlBlock"),
202 text: getText(node)
203 };
204 break;
205
206 case 'html_inline':
207 result = {
208 $class: "".concat(NS, ".HtmlInline"),
209 text: node.data.content
210 };
211 break;
212
213 case 'ol_list':
214 case 'ul_list':
215 {
216 result = {
217 $class: node.data.kind === 'variable' ? "".concat(NS_CICERO, ".ListVariable") : "".concat(NS, ".List"),
218 type: node.type === 'ol_list' ? 'ordered' : 'bullet',
219 delimiter: node.data.delimiter,
220 start: node.data.start,
221 tight: node.data.tight,
222 nodes: []
223 };
224 }
225 break;
226
227 case 'list_item':
228 result = {
229 $class: "".concat(NS, ".Item"),
230 nodes: []
231 };
232 break;
233
234 case 'link':
235 result = {
236 $class: "".concat(NS, ".Link"),
237 destination: node.data.href,
238 title: node.data.title ? node.data.title : '',
239 nodes: []
240 };
241 break;
242
243 case 'image':
244 result = {
245 $class: "".concat(NS, ".Image"),
246 destination: node.data.href,
247 title: node.data.title ? node.data.title : '',
248 nodes: []
249 };
250 break;
251 }
252
253 }
254
255 if (!result) {
256 throw Error("Failed to process node ".concat(JSON.stringify(node)));
257 } // process any children, attaching to first child if it exists (for list items)
258
259
260 if (node.nodes && result.nodes) {
261 _recursive(result.nodes[0] ? result.nodes[0] : result, node.nodes);
262 }
263
264 if (!parent.nodes) {
265 throw new Error("Parent node doesn't have children ".concat(JSON.stringify(parent)));
266 }
267
268 parent.nodes.push(result);
269 });
270}
271/**
272 * Handles a text node
273 * @param {*} node the slate text node
274 * @returns {*} the ast node
275 */
276
277
278function handleText(node) {
279 let strong = null;
280 let emph = null;
281 let result = null;
282 const isBold = node.marks.some(mark => mark.type === 'bold');
283 const isItalic = node.marks.some(mark => mark.type === 'italic');
284 const isCode = node.marks.some(mark => mark.type === 'code');
285
286 if (isCode) {
287 result = {
288 $class: "".concat(NS, ".Code"),
289 text: node.text
290 };
291 }
292
293 const text = {
294 $class: "".concat(NS, ".Text"),
295 text: node.text
296 };
297
298 if (isBold) {
299 strong = {
300 $class: "".concat(NS, ".Strong"),
301 nodes: []
302 };
303 }
304
305 if (isItalic) {
306 emph = {
307 $class: "".concat(NS, ".Emph"),
308 nodes: []
309 };
310 }
311
312 if (strong && emph) {
313 result = emph;
314 emph.nodes.push(strong);
315 strong.nodes.push(text);
316 } else {
317 if (strong) {
318 result = strong;
319 strong.nodes.push(text);
320 }
321
322 if (emph) {
323 result = emph;
324 emph.nodes.push(text);
325 }
326 }
327
328 if (!result) {
329 result = text;
330 }
331
332 return result;
333}
334/**
335 * Handles a variable node
336 * @param {*} node the slate variable node
337 * @returns {*} the ast node
338 */
339
340
341function handleVariable(node) {
342 let result = null;
343 const textNode = node.nodes[0]; // inlines always contain a single text node
344
345 node.nodes = []; // Reset the children for the inline to avoid recursion
346
347 const type = node.type;
348 const baseName = type === 'variable' ? 'Variable' : type === 'conditional' ? 'ConditionalVariable' : 'ComputedVariable';
349 const className = "".concat(NS_CICERO, ".").concat(baseName);
350 result = {
351 $class: className,
352 value: textNode.text
353 };
354 const data = node.data;
355
356 if (Object.prototype.hasOwnProperty.call(data, 'id')) {
357 result.id = data.id;
358 }
359
360 if (Object.prototype.hasOwnProperty.call(data, 'whenTrue')) {
361 result.whenTrue = data.whenTrue;
362 }
363
364 if (Object.prototype.hasOwnProperty.call(data, 'whenFalse')) {
365 result.whenFalse = data.whenFalse;
366 }
367
368 return result;
369}
370
371module.exports = slateToCiceroMarkDom;
\No newline at end of file