UNPKG

5.07 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 {
17 NS_PREFIX_CommonMarkModel
18} = require('@accordproject/markdown-common').CommonMarkModel;
19
20const jsdom = typeof DOMParser === 'undefined' ? require('jsdom') : null;
21
22const typeOf = require('type-of');
23
24const defaultRules = require('./rules');
25
26const JSDOM = jsdom ? jsdom.JSDOM : null;
27/**
28 * Converts an html string to a CiceroMark DOM
29 *
30 */
31
32class ToCiceroMarkVisitor {
33 /**
34 * Construct the parser.
35 * @param {object} [options] configuration options
36 */
37 constructor() {
38 let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
39 let {
40 rules = []
41 } = options;
42 this.options = options;
43 this.rules = [...rules, ...defaultRules];
44 }
45 /**
46 * Filter out cruft newline nodes inserted by the DOM parser.
47 *
48 * @param {Object} element DOM element
49 * @return {Boolean} true if node is not a new line
50 */
51
52
53 cruftNewline(element) {
54 return !(element.nodeName === '#text' && element.nodeValue === '\n');
55 }
56 /**
57 * Deserialize a DOM element.
58 *
59 * @param {Object} element DOM element
60 * @return {Any} node
61 */
62
63
64 deserializeElement(element) {
65 let node; //console.log('tagName', element.tagName);
66
67 if (!element.tagName) {
68 element.tagName = '';
69 }
70
71 const next = elements => {
72 if (Object.prototype.toString.call(elements) === '[object NodeList]') {
73 elements = Array.from(elements);
74 }
75
76 switch (typeOf(elements)) {
77 case 'array':
78 return this.deserializeElements(elements);
79
80 case 'object':
81 return this.deserializeElement(elements);
82
83 case 'null':
84 case 'undefined':
85 return;
86
87 default:
88 throw new Error("The `next` argument was called with invalid children: \"".concat(elements, "\"."));
89 }
90 };
91
92 for (const rule of this.rules) {
93 if (!rule.deserialize) {
94 continue;
95 }
96
97 const ret = rule.deserialize(element, next);
98 const type = typeOf(ret);
99
100 if (type !== 'array' && type !== 'object' && type !== 'null' && type !== 'undefined') {
101 throw new Error("A rule returned an invalid deserialized representation: \"".concat(node, "\"."));
102 }
103
104 if (ret === undefined) {
105 continue;
106 } else if (ret === null) {
107 return null; // } else if (ret.object === 'mark') {
108 // node = this.deserializeMark(ret); // will we need this??
109 } else {
110 node = ret;
111 }
112
113 if (node.object === 'block' || node.object === 'inline') {
114 node.data = node.data || {};
115 node.nodes = node.nodes || [];
116 } else if (node.object === 'text') {
117 node.marks = node.marks || [];
118 node.text = node.text || '';
119 }
120
121 break;
122 }
123
124 return node || next(element.childNodes);
125 }
126 /**
127 * Deserialize an array of DOM elements.
128 *
129 * @param {Array} elements DOM elements
130 * @return {Array} array of nodes
131 */
132
133
134 deserializeElements() {
135 let elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
136 let nodes = [];
137 elements.filter(this.cruftNewline).forEach(element => {
138 // console.log('element -- ', element);
139 const node = this.deserializeElement(element); // console.log('node -- ', node);
140
141 switch (typeOf(node)) {
142 case 'array':
143 nodes = nodes.concat(node);
144 break;
145
146 case 'object':
147 nodes.push(node);
148 break;
149 }
150 });
151 return nodes;
152 }
153 /**
154 * Converts an html string to a CiceroMark DOM
155 * @param {string} input - html string
156 * @param {string} [format] result format, defaults to 'concerto'. Pass
157 * 'json' to return the JSON data.
158 * @returns {*} CiceroMark DOM
159 */
160
161
162 toCiceroMark(input) {
163 let format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'concerto';
164 let fragment; // eslint-disable-next-line no-undef
165
166 if (typeof DOMParser === 'undefined') {
167 fragment = JSDOM.fragment(input);
168 } else {
169 // eslint-disable-next-line no-undef
170 fragment = new DOMParser().parseFromString(input, 'text/html');
171 }
172
173 const children = Array.from(fragment.childNodes); // console.log('children -- ', children);
174
175 const nodes = this.deserializeElements(children); // console.log('nodes', nodes);
176
177 return {
178 '$class': "".concat(NS_PREFIX_CommonMarkModel, 'Document'),
179 nodes,
180 xmlns: 'http://commonmark.org/xml/1.0'
181 };
182 }
183
184}
185
186module.exports = ToCiceroMarkVisitor;
\No newline at end of file