1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | 'use strict';
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function unquoteString(value) {
|
22 | return value.substring(1, value.length - 1);
|
23 | }
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | class ToPdfMakeVisitor {
|
31 | |
32 |
|
33 |
|
34 |
|
35 | constructor(options) {
|
36 | this.options = options;
|
37 | }
|
38 | |
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | static applyMarks(leafNode, parameters) {
|
46 | if (parameters.emph) {
|
47 | leafNode.style = 'Emph';
|
48 | leafNode.italics = true;
|
49 | }
|
50 |
|
51 | if (parameters.strong) {
|
52 | leafNode.style = 'Strong';
|
53 | leafNode.bold = true;
|
54 | }
|
55 |
|
56 | if (parameters.code) {
|
57 | leafNode.style = 'Code';
|
58 | }
|
59 | }
|
60 | |
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | static handleFormattedText(thing, parameters) {
|
69 | const textNode = {
|
70 | text: ToPdfMakeVisitor.getText(thing)
|
71 | };
|
72 | this.applyMarks(textNode, parameters);
|
73 | return textNode;
|
74 | }
|
75 | |
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | static getText(thing) {
|
83 | if (thing.getType() === 'Text') {
|
84 | return thing.text;
|
85 | } else {
|
86 | if (thing.nodes && thing.nodes.length > 0) {
|
87 | return ToPdfMakeVisitor.getText(thing.nodes[0]);
|
88 | } else {
|
89 | return '';
|
90 | }
|
91 | }
|
92 | }
|
93 | |
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | static getHeadingType(thing) {
|
101 | switch (thing.level) {
|
102 | case '1':
|
103 | return 'heading_one';
|
104 |
|
105 | case '2':
|
106 | return 'heading_two';
|
107 |
|
108 | case '3':
|
109 | return 'heading_three';
|
110 |
|
111 | case '4':
|
112 | return 'heading_four';
|
113 |
|
114 | case '5':
|
115 | return 'heading_five';
|
116 |
|
117 | case '6':
|
118 | return 'heading_six';
|
119 |
|
120 | default:
|
121 | return 'heading_one';
|
122 | }
|
123 | }
|
124 | |
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 | processChildren(thing, fieldName, parameters) {
|
134 | const result = [];
|
135 | const nodes = thing[fieldName] ? thing[fieldName] : [];
|
136 | nodes.forEach(node => {
|
137 |
|
138 | const newParameters = {
|
139 | strong: parameters.strong,
|
140 | emph: parameters.emph,
|
141 | code: parameters.code
|
142 | };
|
143 | node.accept(this, newParameters);
|
144 |
|
145 | if (Array.isArray(newParameters.result)) {
|
146 | Array.prototype.push.apply(result, newParameters.result);
|
147 | } else {
|
148 | result.push(newParameters.result);
|
149 | }
|
150 | });
|
151 | return result;
|
152 | }
|
153 | |
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | processChildNodes(thing, parameters) {
|
162 | return this.processChildren(thing, 'nodes', parameters);
|
163 | }
|
164 | |
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 | visit(thing, parameters) {
|
172 | let result = {
|
173 | style: thing.getType()
|
174 | };
|
175 |
|
176 | switch (thing.getType()) {
|
177 | case 'Emph':
|
178 | {
|
179 | parameters.emph = true;
|
180 | result.text = this.processChildNodes(thing, parameters);
|
181 | result.italics = true;
|
182 | }
|
183 | break;
|
184 |
|
185 | case 'Strong':
|
186 | {
|
187 | parameters.strong = true;
|
188 | result.text = this.processChildNodes(thing, parameters);
|
189 | result.bold = true;
|
190 | }
|
191 | break;
|
192 |
|
193 | case 'BlockQuote':
|
194 | case 'Item':
|
195 | case 'Clause':
|
196 | {
|
197 | result.text = this.processChildNodes(thing, parameters);
|
198 | }
|
199 | break;
|
200 |
|
201 | case 'Link':
|
202 | {
|
203 | result.text = thing.nodes[0].text;
|
204 | result.link = thing.destination;
|
205 | }
|
206 | break;
|
207 |
|
208 | case 'Image':
|
209 | {
|
210 | result.image = thing.destination;
|
211 | }
|
212 | break;
|
213 |
|
214 | case 'Paragraph':
|
215 | {
|
216 | const child = this.processChildNodes(thing, parameters);
|
217 |
|
218 | if (child[0] && child[0].style === 'Image') {
|
219 |
|
220 | result.stack = child;
|
221 | } else {
|
222 | result.text = child;
|
223 | result.margin = [0, 5];
|
224 | }
|
225 | }
|
226 | break;
|
227 |
|
228 | case 'EnumVariable':
|
229 | case 'FormattedVariable':
|
230 | case 'Formula':
|
231 | case 'Variable':
|
232 | {
|
233 | const fixedText = thing.elementType === 'String' || thing.identifiedBy ? unquoteString(thing.value) : thing.value;
|
234 | result.text = fixedText;
|
235 | }
|
236 | break;
|
237 |
|
238 | case 'Conditional':
|
239 | {
|
240 | result.text = thing.nodes[0].text;
|
241 | }
|
242 | break;
|
243 |
|
244 | case 'HtmlInline':
|
245 | case 'HtmlBlock':
|
246 | case 'CodeBlock':
|
247 | case 'Code':
|
248 | {
|
249 | result.text = thing.text;
|
250 | }
|
251 | break;
|
252 |
|
253 | case 'Text':
|
254 | {
|
255 | result = ToPdfMakeVisitor.handleFormattedText(thing, parameters);
|
256 | }
|
257 | break;
|
258 |
|
259 | case 'Heading':
|
260 | {
|
261 | const child = this.processChildNodes(thing, parameters);
|
262 | result.style = ToPdfMakeVisitor.getHeadingType(thing);
|
263 | result.text = "\n".concat(child[0].text, "\n");
|
264 | result.tocItem = true;
|
265 | }
|
266 | break;
|
267 |
|
268 | case 'ThematicBreak':
|
269 | {
|
270 | result.text = '';
|
271 | result.pageBreak = 'after';
|
272 | }
|
273 | break;
|
274 |
|
275 | case 'Linebreak':
|
276 | {
|
277 | result.text = '\n';
|
278 | }
|
279 | break;
|
280 |
|
281 | case 'Softbreak':
|
282 | {
|
283 | result.text = ' ';
|
284 | }
|
285 | break;
|
286 |
|
287 | case 'ListBlock':
|
288 | case 'List':
|
289 | {
|
290 | result[thing.type === 'ordered' ? 'ol' : 'ul'] = this.processChildNodes(thing, parameters);
|
291 | }
|
292 | break;
|
293 |
|
294 | case 'Document':
|
295 | {
|
296 | result.content = this.processChildNodes(thing, parameters);
|
297 | }
|
298 | break;
|
299 |
|
300 | default:
|
301 | throw new Error("Unhandled type ".concat(thing.getType()));
|
302 | }
|
303 |
|
304 | parameters.result = result;
|
305 | }
|
306 |
|
307 | }
|
308 |
|
309 | module.exports = ToPdfMakeVisitor; |
\ | No newline at end of file |