UNPKG

8.44 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
15'use strict';
16
17const { ModelManager, Factory, Serializer } = require('@accordproject/concerto-core');
18
19const MarkdownIt = require('markdown-it');
20const MarkdownItCicero = require('@accordproject/markdown-it-cicero');
21const FromMarkdownIt = require('@accordproject/markdown-common').FromMarkdownIt;
22const cicerorules = require('./cicerorules');
23const ToMarkdownCiceroVisitor = require('./ToMarkdownCiceroVisitor');
24const ToCiceroMarkUnwrappedVisitor = require('./ToCiceroMarkUnwrappedVisitor');
25
26const CommonMarkTransformer = require('@accordproject/markdown-common').CommonMarkTransformer;
27const { CommonMarkModel } = require('@accordproject/markdown-common').CommonMarkModel;
28
29const FromCiceroEditVisitor = require('./FromCiceroEditVisitor');
30const ToCommonMarkVisitor = require('./ToCommonMarkVisitor');
31const { CiceroMarkModel } = require('./externalModels/CiceroMarkModel');
32const unquoteVariables = require('./UnquoteVariables');
33
34/**
35 * Converts a CiceroMark DOM to/from a
36 * CommonMark DOM.
37 *
38 * Converts a CiceroMark DOM to/from a markdown string.
39 */
40class CiceroMarkTransformer {
41 /**
42 * Construct the parser.
43 */
44 constructor() {
45 // Setup for Nested Parsing
46 this.commonMark = new CommonMarkTransformer();
47
48 // Setup for validation
49 this.modelManager = new ModelManager();
50 this.modelManager.addModelFile(CommonMarkModel, 'commonmark.cto');
51 this.modelManager.addModelFile(CiceroMarkModel, 'ciceromark.cto');
52 const factory = new Factory(this.modelManager);
53 this.serializer = new Serializer(factory, this.modelManager);
54 }
55
56 /**
57 * Obtain the Clause text for a Clause node
58 * @param {*} input CiceroMark DOM
59 * @returns {*} markdown_cicero string
60 */
61 getClauseText(input) {
62 if (input.$class === 'org.accordproject.ciceromark.Clause') {
63 const docInput = {
64 $class: 'org.accordproject.commonmark.Document',
65 xmlns : 'http://commonmark.org/xml/1.0',
66 nodes: input.nodes,
67 };
68 return this.toMarkdownCicero(docInput);
69 } else {
70 throw new Error('Cannot apply getClauseText to non-clause node');
71 }
72 }
73
74 /**
75 * Retrieve the serializer used by the parser
76 *
77 * @returns {*} a serializer capable of dealing with the Concerto
78 * object returns by parse
79 */
80 getSerializer() {
81 return this.serializer;
82 }
83
84 /**
85 * Converts a CiceroEdit string to a CiceroMark DOM
86 * @param {*} input - ciceroedit string
87 * @returns {*} CiceroMark DOM
88 */
89 fromCiceroEdit(input) {
90 const commonMark = this.commonMark.fromMarkdown(input);
91 const dom = this.serializer.fromJSON(commonMark);
92
93 // Add Cicero nodes
94 const parameters = {
95 ciceroMark: this,
96 commonMark: this.commonMark,
97 modelManager : this.modelManager,
98 serializer : this.serializer,
99 };
100 const visitor = new FromCiceroEditVisitor();
101 dom.accept(visitor, parameters);
102 return this.serializer.toJSON(dom);
103 }
104
105 /**
106 * Converts a CiceroMark DOM to a CiceroMark Unwrapped DOM
107 * @param {object} input - CiceroMark DOM (JSON)
108 * @param {object} [options] configuration options
109 * @param {boolean} [options.unquoteVariables] if true variable quotations are removed
110 * @returns {*} CiceroMark DOM
111 */
112 toCiceroMarkUnwrapped(input,options) {
113 // remove variables, e.g. {{ variable }}, {{% formula %}}
114 if(options && Object.prototype.hasOwnProperty.call(options,'unquoteVariables') && options.unquoteVariables) {
115 input = this.unquote(input);
116 }
117
118 const dom = this.serializer.fromJSON(input);
119
120 // convert to common mark
121 const visitor = new ToCiceroMarkUnwrappedVisitor();
122 dom.accept(visitor, {
123 modelManager : this.modelManager,
124 });
125
126 return this.serializer.toJSON(dom);
127 }
128
129 /**
130 * Converts a CommonMark DOM to a CiceroMark DOM
131 * @param {*} input - CommonMark DOM (in JSON)
132 * @returns {*} CiceroMark DOM
133 */
134 fromCommonMark(input) {
135 return input; // Now the identity
136 }
137
138 /**
139 * Converts a markdown string to a CiceroMark DOM
140 * @param {string} markdown a markdown string
141 * @returns {object} ciceromark object (JSON)
142 */
143 fromMarkdown(markdown) {
144 const commonMarkDom = this.commonMark.fromMarkdown(markdown);
145 return this.fromCommonMark(commonMarkDom);
146 }
147
148 /**
149 * Converts a CiceroMark DOM to a markdown string
150 * @param {*} input CiceroMark DOM
151 * @param {object} [options] configuration options
152 * @returns {*} markdown string
153 */
154 toMarkdown(input, options) {
155 const commonMarkDom = this.toCommonMark(input, options);
156 return this.commonMark.toMarkdown(commonMarkDom);
157 }
158
159 /**
160 * Converts a cicero markdown string to a CiceroMark DOM
161 * @param {string} markdown a cicero markdown string
162 * @param {object} [options] configuration options
163 * @returns {object} ciceromark object (JSON)
164 */
165 fromMarkdownCicero(markdown, options) {
166 const tokens = this.toTokens(markdown);
167 return this.fromTokens(tokens);
168 }
169
170 /**
171 * Converts a CiceroMark DOM to a cicero markdown string
172 * @param {object} input CiceroMark DOM
173 * @returns {string} json commonmark object
174 */
175 toMarkdownCicero(input) {
176 const visitor = new ToMarkdownCiceroVisitor();
177 return visitor.toMarkdownCicero(this.serializer.fromJSON(input));
178 }
179
180 /**
181 * Converts a CiceroMark DOM to a CommonMark DOM
182 * @param {*} input CiceroMark DOM
183 * @param {object} [options] configuration options
184 * @param {boolean} [options.removeFormatting] if true the formatting nodes are removed
185 * @param {boolean} [options.unquoteVariables] if true variable quotations are removed
186 * @returns {*} json commonmark object
187 */
188 toCommonMark(input, options) {
189 let json = this.toCiceroMarkUnwrapped(input,options);
190 const dom = this.serializer.fromJSON(json);
191
192 // convert to common mark
193 const visitor = new ToCommonMarkVisitor(options);
194 dom.accept( visitor, {
195 commonMark: this.commonMark,
196 modelManager : this.modelManager,
197 serializer : this.serializer
198 } );
199
200 let result = this.serializer.toJSON(dom);
201 // remove formatting
202 if(options && options.removeFormatting) {
203 const cmt = new CommonMarkTransformer(options);
204 result = cmt.removeFormatting(result);
205 }
206
207 return result;
208 }
209
210 /**
211 * Unquotes a CiceroMark DOM
212 * @param {object} input CiceroMark DOM
213 * @returns {object} unquoted CiceroMark DOM
214 */
215 unquote(input) {
216 return unquoteVariables(input);
217 }
218
219 /**
220 * Converts a ciceromark string into a token stream
221 *
222 * @param {string} input the string to parse
223 * @returns {*} a markdown-it token stream
224 */
225 toTokens(input) {
226 const parser = new MarkdownIt({html:true}).use(MarkdownItCicero); // XXX HTML inlines and code blocks true
227 const tokenStream = parser.parse(input,{});
228 return tokenStream;
229 }
230
231 /**
232 * Converts a token stream into a CiceroMark DOM object.
233 *
234 * @param {object} tokenStream the token stream
235 * @returns {*} the CiceroMark DOM (JSON)
236 */
237 fromTokens(tokenStream) {
238 const fromMarkdownIt = new FromMarkdownIt(cicerorules);
239 const json = fromMarkdownIt.toCommonMark(tokenStream);
240
241 // validate the object using the model
242 const validJson = this.serializer.fromJSON(json);
243 return this.serializer.toJSON(validJson);
244 }
245
246}
247
248module.exports = CiceroMarkTransformer;
\No newline at end of file