1 | #!/usr/bin/env node
|
2 | (function() {
|
3 | ;
|
4 | var ASCIIDrawing, ASCIIMapping, CSSStyle, CSVDrawing, CoffeeMapping, Context, DOMParser, DSVDrawing, Drawing, Drawings, DynamicSymbol, Input, JSMapping, Mapping, Mappings, SSVDrawing, SVGNS, SVGTilerException, StaticSymbol, Style, Styles, StylusStyle, Symbol, TSVDrawing, XLINKNS, XLSXDrawings, XMLSerializer, allBlank, attributeOrStyle, blankCells, bufferSize, contentType, convertSVG, domImplementation, domRecurse, escapeId, extensionMap, extensionOf, extractOverflowBox, extractZIndex, fs, getHref, graphemeSplitter, help, implicitFinalReturn, inkscapeVersion, isAuto, main, metadata, parseBox, parseNum, path, postprocess, prettyXML, renderPreact, sanitize, splitIntoLines, svgBBox, svgtiler, unrecognizedSymbol, whitespace, xmldom, zeroSizeReplacement,
|
5 | indexOf = [].indexOf,
|
6 | hasProp = {}.hasOwnProperty;
|
7 |
|
8 | if (typeof window === "undefined" || window === null) {
|
9 | path = require('path');
|
10 | fs = require('fs');
|
11 | xmldom = require('@xmldom/xmldom');
|
12 | DOMParser = xmldom.DOMParser;
|
13 | domImplementation = new xmldom.DOMImplementation();
|
14 | XMLSerializer = xmldom.XMLSerializer;
|
15 | prettyXML = require('prettify-xml');
|
16 | graphemeSplitter = new require('grapheme-splitter')();
|
17 | metadata = require('../package.json');
|
18 | require('coffeescript/register');
|
19 | } else {
|
20 | DOMParser = window.DOMParser;
|
21 | domImplementation = document.implementation;
|
22 | XMLSerializer = window.XMLSerializer;
|
23 | path = {
|
24 | extname: function(x) {
|
25 | return /\.[^\/]+$/.exec(x)[0];
|
26 | },
|
27 | dirname: function(x) {
|
28 | return /[^]*\/|/.exec(x)[0];
|
29 | }
|
30 | };
|
31 | graphemeSplitter = {
|
32 | splitGraphemes: function(x) {
|
33 | return x.split('');
|
34 | }
|
35 | };
|
36 | metadata = {
|
37 | version: '(web)'
|
38 | };
|
39 | }
|
40 |
|
41 | SVGNS = 'http://www.w3.org/2000/svg';
|
42 |
|
43 | XLINKNS = 'http://www.w3.org/1999/xlink';
|
44 |
|
45 | splitIntoLines = function(data) {
|
46 | return data.replace('\r\n', '\n').replace('\r', '\n').split('\n');
|
47 | };
|
48 |
|
49 | whitespace = /[\s\uFEFF\xA0]+/;
|
50 |
|
51 | extensionOf = function(filename) {
|
52 | return path.extname(filename).toLowerCase();
|
53 | };
|
54 |
|
55 | SVGTilerException = class SVGTilerException {
|
56 | constructor(message) {
|
57 | this.message = message;
|
58 | }
|
59 |
|
60 | toString() {
|
61 | return `svgtiler: ${this.message}`;
|
62 | }
|
63 |
|
64 | };
|
65 |
|
66 | parseBox = function(box) {
|
67 | if (!box) {
|
68 | return null;
|
69 | }
|
70 | box = box.split(/\s*[\s,]\s*/).map(parseNum);
|
71 | if (indexOf.call(box, null) >= 0) {
|
72 | return null;
|
73 | }
|
74 | return box;
|
75 | };
|
76 |
|
77 | extractOverflowBox = function(xml) {
|
78 | var box;
|
79 |
|
80 |
|
81 | box = xml.documentElement.getAttribute('overflowBox');
|
82 | xml.documentElement.removeAttribute('overflowBox');
|
83 | return parseBox(box);
|
84 | };
|
85 |
|
86 | parseNum = function(x) {
|
87 | var parsed;
|
88 | parsed = parseFloat(x);
|
89 | if (isNaN(parsed)) {
|
90 | return null;
|
91 | } else {
|
92 | return parsed;
|
93 | }
|
94 | };
|
95 |
|
96 | svgBBox = function(xml) {
|
97 | var recurse, viewBox;
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | if (xml.documentElement.hasAttribute('viewBox')) {
|
105 | return parseBox(xml.documentElement.getAttribute('viewBox'));
|
106 | } else {
|
107 | recurse = function(node) {
|
108 | var child, coord, cx, cy, point, points, r, ref, ref1, ref10, ref11, ref12, ref13, ref14, ref15, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rx, ry, viewBox, viewBoxes, x1, x2, xmax, xmin, xs, y1, y2, ymax, ymin, ys;
|
109 | if (node.nodeType !== node.ELEMENT_NODE || ((ref = node.nodeName) === 'defs' || ref === 'use')) {
|
110 | return null;
|
111 | }
|
112 |
|
113 | if (node.nodeName === 'symbol' && node !== xml.documentElement) {
|
114 | return null;
|
115 | }
|
116 | switch (node.tagName) {
|
117 | case 'rect':
|
118 | case 'image':
|
119 |
|
120 | return [(ref1 = parseNum(node.getAttribute('x'))) != null ? ref1 : 0, (ref2 = parseNum(node.getAttribute('y'))) != null ? ref2 : 0, (ref3 = parseNum(node.getAttribute('width'))) != null ? ref3 : 0, (ref4 = parseNum(node.getAttribute('height'))) != null ? ref4 : 0];
|
121 | case 'circle':
|
122 | cx = (ref5 = parseNum(node.getAttribute('cx'))) != null ? ref5 : 0;
|
123 | cy = (ref6 = parseNum(node.getAttribute('cy'))) != null ? ref6 : 0;
|
124 | r = (ref7 = parseNum(node.getAttribute('r'))) != null ? ref7 : 0;
|
125 | return [cx - r, cy - r, 2 * r, 2 * r];
|
126 | case 'ellipse':
|
127 | cx = (ref8 = parseNum(node.getAttribute('cx'))) != null ? ref8 : 0;
|
128 | cy = (ref9 = parseNum(node.getAttribute('cy'))) != null ? ref9 : 0;
|
129 | rx = (ref10 = parseNum(node.getAttribute('rx'))) != null ? ref10 : 0;
|
130 | ry = (ref11 = parseNum(node.getAttribute('ry'))) != null ? ref11 : 0;
|
131 | return [cx - rx, cy - ry, 2 * rx, 2 * ry];
|
132 | case 'line':
|
133 | x1 = (ref12 = parseNum(node.getAttribute('x1'))) != null ? ref12 : 0;
|
134 | y1 = (ref13 = parseNum(node.getAttribute('y1'))) != null ? ref13 : 0;
|
135 | x2 = (ref14 = parseNum(node.getAttribute('x2'))) != null ? ref14 : 0;
|
136 | y2 = (ref15 = parseNum(node.getAttribute('y2'))) != null ? ref15 : 0;
|
137 | xmin = Math.min(x1, x2);
|
138 | ymin = Math.min(y1, y2);
|
139 | return [xmin, ymin, Math.max(x1, x2) - xmin, Math.max(y1, y2) - ymin];
|
140 | case 'polyline':
|
141 | case 'polygon':
|
142 | points = (function() {
|
143 | var k, len, ref16, results;
|
144 | ref16 = node.getAttribute('points').trim().split(/\s+/);
|
145 | results = [];
|
146 | for (k = 0, len = ref16.length; k < len; k++) {
|
147 | point = ref16[k];
|
148 | results.push((function() {
|
149 | var l, len1, ref17, results1;
|
150 | ref17 = point.split(/,/);
|
151 | results1 = [];
|
152 | for (l = 0, len1 = ref17.length; l < len1; l++) {
|
153 | coord = ref17[l];
|
154 | results1.push(parseFloat(coord));
|
155 | }
|
156 | return results1;
|
157 | })());
|
158 | }
|
159 | return results;
|
160 | })();
|
161 | xs = (function() {
|
162 | var k, len, results;
|
163 | results = [];
|
164 | for (k = 0, len = points.length; k < len; k++) {
|
165 | point = points[k];
|
166 | results.push(point[0]);
|
167 | }
|
168 | return results;
|
169 | })();
|
170 | ys = (function() {
|
171 | var k, len, results;
|
172 | results = [];
|
173 | for (k = 0, len = points.length; k < len; k++) {
|
174 | point = points[k];
|
175 | results.push(point[1]);
|
176 | }
|
177 | return results;
|
178 | })();
|
179 | xmin = Math.min(...xs);
|
180 | ymin = Math.min(...ys);
|
181 | if (isNaN(xmin) || isNaN(ymin)) {
|
182 | return null;
|
183 | } else {
|
184 | return [xmin, ymin, Math.max(...xs) - xmin, Math.max(...ys) - ymin];
|
185 | }
|
186 | break;
|
187 | default:
|
188 | viewBoxes = (function() {
|
189 | var k, len, ref16, results;
|
190 | ref16 = node.childNodes;
|
191 | results = [];
|
192 | for (k = 0, len = ref16.length; k < len; k++) {
|
193 | child = ref16[k];
|
194 | results.push(recurse(child));
|
195 | }
|
196 | return results;
|
197 | })();
|
198 | viewBoxes = (function() {
|
199 | var k, len, results;
|
200 | results = [];
|
201 | for (k = 0, len = viewBoxes.length; k < len; k++) {
|
202 | viewBox = viewBoxes[k];
|
203 | if (viewBox != null) {
|
204 | results.push(viewBox);
|
205 | }
|
206 | }
|
207 | return results;
|
208 | })();
|
209 | xmin = Math.min(...((function() {
|
210 | var k, len, results;
|
211 | results = [];
|
212 | for (k = 0, len = viewBoxes.length; k < len; k++) {
|
213 | viewBox = viewBoxes[k];
|
214 | results.push(viewBox[0]);
|
215 | }
|
216 | return results;
|
217 | })()));
|
218 | ymin = Math.min(...((function() {
|
219 | var k, len, results;
|
220 | results = [];
|
221 | for (k = 0, len = viewBoxes.length; k < len; k++) {
|
222 | viewBox = viewBoxes[k];
|
223 | results.push(viewBox[1]);
|
224 | }
|
225 | return results;
|
226 | })()));
|
227 | xmax = Math.max(...((function() {
|
228 | var k, len, results;
|
229 | results = [];
|
230 | for (k = 0, len = viewBoxes.length; k < len; k++) {
|
231 | viewBox = viewBoxes[k];
|
232 | results.push(viewBox[0] + viewBox[2]);
|
233 | }
|
234 | return results;
|
235 | })()));
|
236 | ymax = Math.max(...((function() {
|
237 | var k, len, results;
|
238 | results = [];
|
239 | for (k = 0, len = viewBoxes.length; k < len; k++) {
|
240 | viewBox = viewBoxes[k];
|
241 | results.push(viewBox[1] + viewBox[3]);
|
242 | }
|
243 | return results;
|
244 | })()));
|
245 | return [xmin, ymin, xmax - xmin, ymax - ymin];
|
246 | }
|
247 | };
|
248 | viewBox = recurse(xml.documentElement);
|
249 | if ((viewBox == null) || indexOf.call(viewBox, 2e308) >= 0 || indexOf.call(viewBox, -2e308) >= 0) {
|
250 | return null;
|
251 | } else {
|
252 | return viewBox;
|
253 | }
|
254 | }
|
255 | };
|
256 |
|
257 | isAuto = function(xml, prop) {
|
258 | return xml.documentElement.hasAttribute(prop) && /^\s*auto\s*$/i.test(xml.documentElement.getAttribute(prop));
|
259 | };
|
260 |
|
261 | attributeOrStyle = function(node, attr, styleKey = attr) {
|
262 | var match, style, value;
|
263 | if (value = node.getAttribute(attr)) {
|
264 | return value.trim();
|
265 | } else {
|
266 | style = node.getAttribute('style');
|
267 | if (style) {
|
268 | match = RegExp(`(?:^|;)\\s*${styleKey}\\s*:\\s*([^;\\s][^;]*)`, "i").exec(style);
|
269 | return match != null ? match[1] : void 0;
|
270 | }
|
271 | }
|
272 | };
|
273 |
|
274 | getHref = function(node) {
|
275 | var href, k, key, len, ref;
|
276 | ref = ['xlink:href', 'href'];
|
277 | for (k = 0, len = ref.length; k < len; k++) {
|
278 | key = ref[k];
|
279 | if (href = node.getAttribute(key)) {
|
280 | return {
|
281 | key: key,
|
282 | href: href
|
283 | };
|
284 | }
|
285 | }
|
286 | return {
|
287 | key: null,
|
288 | href: null
|
289 | };
|
290 | };
|
291 |
|
292 | extractZIndex = function(node) {
|
293 | var z;
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 | z = parseInt(attributeOrStyle(node, 'z-index'));
|
301 | node.removeAttribute('z-index');
|
302 | if (isNaN(z)) {
|
303 | return 0;
|
304 | } else {
|
305 | return z;
|
306 | }
|
307 | };
|
308 |
|
309 | domRecurse = function(node, callback) {
|
310 | var child, nextChild;
|
311 | |
312 |
|
313 |
|
314 |
|
315 |
|
316 |
|
317 | if (!node.hasChildNodes()) {
|
318 | return;
|
319 | }
|
320 | child = node.lastChild;
|
321 | while (child != null) {
|
322 | nextChild = child.previousSibling;
|
323 | if (callback(child, node)) {
|
324 | domRecurse(child, callback);
|
325 | }
|
326 | child = nextChild;
|
327 | }
|
328 | return null;
|
329 | };
|
330 |
|
331 | contentType = {
|
332 | '.png': 'image/png',
|
333 | '.jpg': 'image/jpeg',
|
334 | '.jpeg': 'image/jpeg',
|
335 | '.gif': 'image/gif',
|
336 | '.svg': 'image/svg+xml'
|
337 | };
|
338 |
|
339 | renderPreact = function(data) {
|
340 | if (typeof data === 'object' && (data.type != null) && (data.props != null)) {
|
341 | data = require('preact-render-to-string')(data);
|
342 | }
|
343 | return data;
|
344 | };
|
345 |
|
346 | Symbol = (function() {
|
347 | class Symbol {
|
348 | static parse(key, data, dirname) {
|
349 | var extension, filename;
|
350 | if (data == null) {
|
351 | throw new SVGTilerException(`Attempt to create symbol '${key}' without data`);
|
352 | } else if (typeof data === 'function') {
|
353 | return new DynamicSymbol(key, data, dirname);
|
354 | } else if (data.function != null) {
|
355 | return new DynamicSymbol(key, data.function, dirname);
|
356 | } else {
|
357 |
|
358 |
|
359 |
|
360 | data = renderPreact(data);
|
361 | return new StaticSymbol(key, (function() {
|
362 | if (typeof data === 'string') {
|
363 | if (data.trim() === '') {
|
364 | return {
|
365 | svg: '<symbol viewBox="0 0 0 0"/>'
|
366 | };
|
367 | } else if (data.indexOf('<') < 0) {
|
368 | if (dirname != null) {
|
369 | filename = path.join(dirname, data);
|
370 | } else {
|
371 | filename = data;
|
372 | }
|
373 | extension = extensionOf(data);
|
374 |
|
375 |
|
376 |
|
377 | switch (extension) {
|
378 | case '.png':
|
379 | case '.jpg':
|
380 | case '.jpeg':
|
381 | case '.gif':
|
382 | return {
|
383 | dirname: dirname,
|
384 | svg: `<image ${Drawing.hrefAttr()}="${encodeURI(data)}"/>`
|
385 | };
|
386 | case '.svg':
|
387 | return {
|
388 | dirname: path.dirname(filename),
|
389 | filename: filename,
|
390 | svg: fs.readFileSync(filename, {
|
391 | encoding: this.svgEncoding
|
392 | })
|
393 | };
|
394 | default:
|
395 | throw new SVGTilerException(`Unrecognized extension in filename '${data}' for symbol '${key}'`);
|
396 | }
|
397 | } else {
|
398 | return {
|
399 | dirname: dirname,
|
400 | svg: data
|
401 | };
|
402 | }
|
403 | } else {
|
404 | return data;
|
405 | }
|
406 | }).call(this));
|
407 | }
|
408 | }
|
409 |
|
410 | includes(substring) {
|
411 | return this.key.indexOf(substring) >= 0;
|
412 | }
|
413 |
|
414 |
|
415 | match(regex) {
|
416 | return this.key.match(regex);
|
417 | }
|
418 |
|
419 | };
|
420 |
|
421 | Symbol.svgEncoding = 'utf8';
|
422 |
|
423 | Symbol.forceWidth = null;
|
424 |
|
425 | Symbol.forceHeight = null;
|
426 |
|
427 | Symbol.texText = false;
|
428 |
|
429 |
|
430 |
|
431 |
|
432 | Symbol.overflowDefault = 'visible';
|
433 |
|
434 | return Symbol;
|
435 |
|
436 | }).call(this);
|
437 |
|
438 | escapeId = function(key) {
|
439 | |
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 |
|
453 |
|
454 |
|
455 | return (encodeURIComponent(key).replace(/[_\.!~*'()]|^[\-0-9]/g, function(c) {
|
456 | return `%${c.charCodeAt(0).toString(16).toUpperCase()}`;
|
457 | }).replace(/%/g, '_')) || '_blank';
|
458 | };
|
459 |
|
460 | zeroSizeReplacement = 1;
|
461 |
|
462 | StaticSymbol = (function() {
|
463 | class StaticSymbol extends Symbol {
|
464 | constructor(key1, options) {
|
465 | var attribute, child, doc, k, key, l, len, len1, node, overflow, ref, ref1, ref2, ref3, symbol, value, warnings;
|
466 | super();
|
467 | this.key = key1;
|
468 | for (key in options) {
|
469 | if (!hasProp.call(options, key)) continue;
|
470 | value = options[key];
|
471 | this[key] = value;
|
472 | }
|
473 |
|
474 |
|
475 |
|
476 | this.svg = this.svg.replace(/^\s*<(?:[^<>'"\/]|'[^']*'|"[^"]*")*\s*(\/?\s*>)/, function(match, end) {
|
477 | if (indexOf.call(match, 'xmlns') < 0) {
|
478 | match = match.slice(0, match.length - end.length) + ` xmlns='${SVGNS}'` + match.slice(match.length - end.length);
|
479 | }
|
480 | return match;
|
481 | });
|
482 | this.xml = new DOMParser({
|
483 | locator: {
|
484 | line: 1,
|
485 | col: 1
|
486 | },
|
487 | errorHandler: (level, msg, indent = ' ') => {
|
488 | msg = msg.replace(/^\[xmldom [^\[\]]*\]\t/, '');
|
489 | msg = msg.replace(/@#\[line:(\d+),col:(\d+)\]$/, (match, line, col) => {
|
490 | var lines;
|
491 | lines = this.svg.split('\n');
|
492 | return (line > 1 ? indent + lines[line - 2] + '\n' : '') + indent + lines[line - 1] + '\n' + indent + ' '.repeat(col - 1) + '^^^' + (line < lines.length ? '\n' + indent + lines[line] : '');
|
493 | });
|
494 | return console.error(`SVG parse ${level} in symbol '${this.key}': ${msg}`);
|
495 | }
|
496 | }).parseFromString(this.svg, 'image/svg+xml');
|
497 |
|
498 |
|
499 | this.xml.documentElement.removeAttribute('xmlns');
|
500 |
|
501 | symbol = this.xml.createElementNS(SVGNS, 'symbol');
|
502 | symbol.setAttribute('id', this.id = escapeId(this.key));
|
503 |
|
504 | if (((ref = this.xml.documentElement.nodeName) === 'symbol' || ref === 'svg') && (this.xml.documentElement.nextSibling == null)) {
|
505 | ref1 = this.xml.documentElement.attributes;
|
506 | for (k = 0, len = ref1.length; k < len; k++) {
|
507 | attribute = ref1[k];
|
508 | if (!(((ref2 = attribute.name) === 'version' || ref2 === 'id') || attribute.name.slice(0, 5) === 'xmlns')) {
|
509 | symbol.setAttribute(attribute.name, attribute.value);
|
510 | }
|
511 | }
|
512 | doc = this.xml.documentElement;
|
513 | this.xml.removeChild(this.xml.documentElement);
|
514 | } else {
|
515 | doc = this.xml;
|
516 | }
|
517 | ref3 = (function() {
|
518 | var len1, n, ref3, results;
|
519 | ref3 = doc.childNodes;
|
520 | results = [];
|
521 | for (n = 0, len1 = ref3.length; n < len1; n++) {
|
522 | node = ref3[n];
|
523 | results.push(node);
|
524 | }
|
525 | return results;
|
526 | })();
|
527 | for (l = 0, len1 = ref3.length; l < len1; l++) {
|
528 | child = ref3[l];
|
529 | symbol.appendChild(child);
|
530 | }
|
531 | this.xml.appendChild(symbol);
|
532 |
|
533 | domRecurse(this.xml.documentElement, (node) => {
|
534 | |
535 |
|
536 |
|
537 |
|
538 |
|
539 |
|
540 |
|
541 |
|
542 | var e, filedata, filename, height, href, ref4, rendering, size, style, type, width;
|
543 | if (node.nodeName === 'image') {
|
544 | rendering = attributeOrStyle(node, 'image-rendering');
|
545 | if ((rendering == null) || (rendering === 'optimizeSpeed' || rendering === 'pixelated')) {
|
546 | node.setAttribute('image-rendering', 'optimizeSpeed');
|
547 | style = (ref4 = node.getAttribute('style')) != null ? ref4 : '';
|
548 | style = style.replace(/(^|;)\s*image-rendering\s*:\s*\w+\s*($|;)/, function(m, before, after) {
|
549 | return before || after || '';
|
550 | });
|
551 | if (style) {
|
552 | style += ';';
|
553 | }
|
554 | node.setAttribute('style', style + 'image-rendering:pixelated');
|
555 | }
|
556 |
|
557 | ({href, key} = getHref(node));
|
558 | filename = href;
|
559 | if ((this.dirname != null) && filename) {
|
560 | filename = path.join(this.dirname, filename);
|
561 | }
|
562 | if ((filename != null) && !/^data:|file:|[a-z]+:\/\//.test(filename)) {
|
563 | filedata = null;
|
564 | try {
|
565 | if (typeof window === "undefined" || window === null) {
|
566 | filedata = fs.readFileSync(filename);
|
567 | }
|
568 | } catch (error1) {
|
569 | e = error1;
|
570 | console.warn(`Failed to read image '${filename}': ${e}`);
|
571 | }
|
572 |
|
573 | size = null;
|
574 | if (typeof window === "undefined" || window === null) {
|
575 | try {
|
576 | size = require('image-size')(filedata != null ? filedata : filename);
|
577 | } catch (error1) {
|
578 | e = error1;
|
579 | console.warn(`Failed to detect size of image '${filename}': ${e}`);
|
580 | }
|
581 | }
|
582 | if (size != null) {
|
583 |
|
584 | if (!isNaN(width = parseFloat(node.getAttribute('width')))) {
|
585 | node.setAttribute('height', size.height * (width / size.width));
|
586 | } else if (!isNaN(height = parseFloat(node.getAttribute('height')))) {
|
587 | node.setAttribute('width', size.width * (height / size.height));
|
588 | } else {
|
589 |
|
590 | node.setAttribute('width', size.width);
|
591 | node.setAttribute('height', size.height);
|
592 | }
|
593 | }
|
594 |
|
595 | if ((filedata != null) && Drawing.inlineImages) {
|
596 | type = contentType[extensionOf(filename)];
|
597 | if (type != null) {
|
598 | node.setAttribute("data-filename", filename);
|
599 | if (size != null) {
|
600 | node.setAttribute("data-width", size.width);
|
601 | node.setAttribute("data-height", size.height);
|
602 | }
|
603 | node.setAttribute(key, `data:${type};base64,${filedata.toString('base64')}`);
|
604 | }
|
605 | }
|
606 | }
|
607 | return false;
|
608 | } else {
|
609 | return true;
|
610 | }
|
611 | });
|
612 |
|
613 | this.viewBox = svgBBox(this.xml);
|
614 |
|
615 | overflow = attributeOrStyle(this.xml.documentElement, 'overflow');
|
616 | if ((this.constructor.overflowDefault != null) && (overflow == null)) {
|
617 | this.xml.documentElement.setAttribute('overflow', overflow = this.constructor.overflowDefault);
|
618 | }
|
619 | this.overflowVisible = (overflow != null) && /^\s*(visible|scroll)\b/.test(overflow);
|
620 | this.width = this.height = null;
|
621 | if (this.viewBox != null) {
|
622 | this.width = this.viewBox[2];
|
623 | this.height = this.viewBox[3];
|
624 | |
625 |
|
626 |
|
627 |
|
628 |
|
629 | if (this.overflowVisible) {
|
630 | if (this.width === 0) {
|
631 | this.viewBox[2] = zeroSizeReplacement;
|
632 | }
|
633 | if (this.height === 0) {
|
634 | this.viewBox[3] = zeroSizeReplacement;
|
635 | }
|
636 | }
|
637 |
|
638 |
|
639 | this.xml.documentElement.setAttribute('viewBox', this.viewBox.join(' '));
|
640 | }
|
641 | this.overflowBox = extractOverflowBox(this.xml);
|
642 | if (Symbol.forceWidth != null) {
|
643 | this.width = Symbol.forceWidth;
|
644 | }
|
645 | if (Symbol.forceHeight != null) {
|
646 | this.height = Symbol.forceHeight;
|
647 | }
|
648 | warnings = [];
|
649 | if (this.width == null) {
|
650 | warnings.push('width');
|
651 | this.width = 0;
|
652 | }
|
653 | if (this.height == null) {
|
654 | warnings.push('height');
|
655 | this.height = 0;
|
656 | }
|
657 | if (warnings.length > 0) {
|
658 | console.warn(`Failed to detect ${warnings.join(' and ')} of SVG for symbol '${this.key}'`);
|
659 | }
|
660 |
|
661 |
|
662 | this.autoWidth = isAuto(this.xml, 'width');
|
663 | this.autoHeight = isAuto(this.xml, 'height');
|
664 | if (this.autoWidth) {
|
665 | this.xml.documentElement.removeAttribute('width');
|
666 | }
|
667 | if (this.autoHeight) {
|
668 | this.xml.documentElement.removeAttribute('height');
|
669 | }
|
670 | this.zIndex = extractZIndex(this.xml.documentElement);
|
671 |
|
672 | if (Symbol.texText) {
|
673 | this.text = [];
|
674 | domRecurse(this.xml.documentElement, (node, parent) => {
|
675 | if (node.nodeName === 'text') {
|
676 | this.text.push(node);
|
677 | parent.removeChild(node);
|
678 | return false;
|
679 | } else {
|
680 | return true;
|
681 | }
|
682 | });
|
683 | }
|
684 | }
|
685 |
|
686 | setId(id) {
|
687 | this.id = id;
|
688 | return this.xml.documentElement.setAttribute('id', id);
|
689 | }
|
690 |
|
691 | use() {
|
692 | return this;
|
693 | }
|
694 |
|
695 | };
|
696 |
|
697 | StaticSymbol.prototype.usesContext = false;
|
698 |
|
699 | return StaticSymbol;
|
700 |
|
701 | }).call(this);
|
702 |
|
703 | DynamicSymbol = (function() {
|
704 | class DynamicSymbol extends Symbol {
|
705 | constructor(key1, func1, dirname1) {
|
706 | super();
|
707 | this.key = key1;
|
708 | this.func = func1;
|
709 | this.dirname = dirname1;
|
710 | this.versions = {};
|
711 | this.nversions = 0;
|
712 | this.constructor.all.push(this);
|
713 | }
|
714 |
|
715 | static resetAll() {
|
716 | var k, len, ref, results, symbol;
|
717 | ref = this.all;
|
718 |
|
719 |
|
720 | results = [];
|
721 | for (k = 0, len = ref.length; k < len; k++) {
|
722 | symbol = ref[k];
|
723 | symbol.versions = {};
|
724 | results.push(symbol.nversions = 0);
|
725 | }
|
726 | return results;
|
727 | }
|
728 |
|
729 | use(context) {
|
730 | var result, string, version;
|
731 | result = this.func.call(context);
|
732 | if (result == null) {
|
733 | throw new Error(`Function for symbol ${this.key} returned ${result}`);
|
734 | }
|
735 |
|
736 |
|
737 | result = renderPreact(result);
|
738 |
|
739 |
|
740 | string = JSON.stringify(result);
|
741 | if (!(string in this.versions)) {
|
742 | version = this.nversions++;
|
743 | this.versions[string] = Symbol.parse(`${this.key}_v${version}`, result, this.dirname);
|
744 | this.versions[string].setId(`${escapeId(this.key)}_v${version}`);
|
745 | }
|
746 | return this.versions[string];
|
747 | }
|
748 |
|
749 | };
|
750 |
|
751 | DynamicSymbol.all = [];
|
752 |
|
753 | DynamicSymbol.prototype.usesContext = true;
|
754 |
|
755 | return DynamicSymbol;
|
756 |
|
757 | }).call(this);
|
758 |
|
759 |
|
760 |
|
761 |
|
762 | unrecognizedSymbol = new StaticSymbol('_unrecognized', {
|
763 | svg: `<symbol viewBox="0 0 200 200" preserveAspectRatio="none" width="auto" height="auto">
|
764 | <rect width="200" height="200" fill="yellow"/>
|
765 | <path stroke="none" fill="red" d="M 200,100 100,200 0,100 100,0 200,100 z M 135.64709,74.70585 q 0,-13.52935 -10.00006,-22.52943 -9.99999,-8.99999 -24.35289,-8.99999 -17.29415,0 -30.117661,5.29409 L 69.05879,69.52938 q 9.764731,-6.23528 21.52944,-6.23528 8.82356,0 14.58824,4.82351 5.76469,4.82351 5.76469,12.70589 0,8.5883 -9.94117,21.70588 -9.94117,13.11766 -9.94117,26.76473 l 17.88236,0 q 0,-6.3529 6.9412,-14.9412 11.76471,-14.58816 12.82351,-16.35289 6.9412,-11.05887 6.9412,-23.29417 z m -22.00003,92.11771 0,-24.70585 -27.29412,0 0,24.70585 27.29412,0 z"/>
|
766 | </symbol>`
|
767 | });
|
768 |
|
769 | unrecognizedSymbol.setId('_unrecognized');
|
770 |
|
771 | Input = (function() {
|
772 | class Input {
|
773 | static parseFile(filename, filedata) {
|
774 | var input;
|
775 |
|
776 | input = new (this)();
|
777 | input.filename = filename;
|
778 | if (filedata == null) {
|
779 | filedata = fs.readFileSync(filename, {
|
780 | encoding: this.encoding
|
781 | });
|
782 | }
|
783 | input.parse(filedata);
|
784 | return input;
|
785 | }
|
786 |
|
787 | static recognize(filename, filedata) {
|
788 | var extension;
|
789 |
|
790 | extension = extensionOf(filename);
|
791 | if (extension in extensionMap) {
|
792 | return extensionMap[extension].parseFile(filename, filedata);
|
793 | } else {
|
794 | throw new SVGTilerException(`Unrecognized extension in filename ${filename}`);
|
795 | }
|
796 | }
|
797 |
|
798 | };
|
799 |
|
800 | Input.encoding = 'utf8';
|
801 |
|
802 | return Input;
|
803 |
|
804 | }).call(this);
|
805 |
|
806 | Style = class Style extends Input {
|
807 | load(css) {
|
808 | this.css = css;
|
809 | }
|
810 |
|
811 | };
|
812 |
|
813 | CSSStyle = (function() {
|
814 | class CSSStyle extends Style {
|
815 | parse(filedata) {
|
816 | return this.load(filedata);
|
817 | }
|
818 |
|
819 | };
|
820 |
|
821 | CSSStyle.title = "CSS style file";
|
822 |
|
823 | return CSSStyle;
|
824 |
|
825 | }).call(this);
|
826 |
|
827 | StylusStyle = (function() {
|
828 | class StylusStyle extends Style {
|
829 | parse(filedata) {
|
830 | var styl;
|
831 | styl = require('stylus')(filedata, {
|
832 | filename: this.filename
|
833 | });
|
834 | return this.load(styl.render());
|
835 | }
|
836 |
|
837 | };
|
838 |
|
839 | StylusStyle.title = "Stylus style file (https://stylus-lang.com/)";
|
840 |
|
841 | return StylusStyle;
|
842 |
|
843 | }).call(this);
|
844 |
|
845 | Styles = class Styles {
|
846 | constructor(styles1 = []) {
|
847 | this.styles = styles1;
|
848 | }
|
849 |
|
850 | push(map) {
|
851 | return this.styles.push(map);
|
852 | }
|
853 |
|
854 | };
|
855 |
|
856 | Mapping = class Mapping extends Input {
|
857 | load(data) {
|
858 | this.map = {};
|
859 | if (typeof data === 'function') {
|
860 | return this.function = data;
|
861 | } else {
|
862 | return this.merge(data);
|
863 | }
|
864 | }
|
865 |
|
866 | merge(data) {
|
867 | var dirname, key, results, value;
|
868 | if (this.filename != null) {
|
869 | dirname = path.dirname(this.filename);
|
870 | }
|
871 | results = [];
|
872 | for (key in data) {
|
873 | if (!hasProp.call(data, key)) continue;
|
874 | value = data[key];
|
875 | if (!(value instanceof Symbol)) {
|
876 | value = Symbol.parse(key, value, dirname);
|
877 | }
|
878 | results.push(this.map[key] = value);
|
879 | }
|
880 | return results;
|
881 | }
|
882 |
|
883 | lookup(key) {
|
884 | var dirname, value;
|
885 | if (this.filename != null) {
|
886 | dirname = path.dirname(this.filename);
|
887 | }
|
888 | key = key.toString();
|
889 | if (key in this.map) {
|
890 | return this.map[key];
|
891 | } else if (this.function != null) {
|
892 |
|
893 |
|
894 |
|
895 | value = this.function(key);
|
896 | if (value != null) {
|
897 | return this.map[key] = Symbol.parse(key, value, dirname);
|
898 | } else {
|
899 | return value;
|
900 | }
|
901 | } else {
|
902 | return void 0;
|
903 | }
|
904 | }
|
905 |
|
906 | };
|
907 |
|
908 | ASCIIMapping = (function() {
|
909 | class ASCIIMapping extends Mapping {
|
910 | parse(data) {
|
911 | var k, key, len, line, map, ref, separator;
|
912 | map = {};
|
913 | ref = splitIntoLines(data);
|
914 | for (k = 0, len = ref.length; k < len; k++) {
|
915 | line = ref[k];
|
916 | separator = whitespace.exec(line);
|
917 | if (separator == null) {
|
918 | continue;
|
919 | }
|
920 | if (separator.index === 0) {
|
921 | if (separator[0].length === 1) {
|
922 |
|
923 | key = '';
|
924 | } else {
|
925 |
|
926 | key = line[0];
|
927 | }
|
928 | } else {
|
929 | key = line.slice(0, separator.index);
|
930 | }
|
931 | map[key] = line.slice(separator.index + separator[0].length);
|
932 | }
|
933 | return this.load(map);
|
934 | }
|
935 |
|
936 | };
|
937 |
|
938 | ASCIIMapping.title = "ASCII mapping file";
|
939 |
|
940 | ASCIIMapping.help = "Each line is <symbol-name><space><raw SVG or filename.svg>";
|
941 |
|
942 | return ASCIIMapping;
|
943 |
|
944 | }).call(this);
|
945 |
|
946 |
|
947 |
|
948 | implicitFinalReturn = function({types}) {
|
949 | return {
|
950 | visitor: {
|
951 | Program: function(path) {
|
952 | var body, last, returnLast;
|
953 | body = path.get('body');
|
954 | if (!body.length) {
|
955 | return;
|
956 | }
|
957 | last = body[body.length - 1];
|
958 | if (last.node.type === 'ExpressionStatement') {
|
959 | returnLast = types.returnStatement(last.node.expression);
|
960 | returnLast.leadingComments = last.node.leadingComments;
|
961 | returnLast.innerComments = last.node.innerComments;
|
962 | returnLast.trailingComments = last.node.trailingComments;
|
963 | last.replaceWith(returnLast);
|
964 | }
|
965 | return void 0;
|
966 | }
|
967 | }
|
968 | };
|
969 | };
|
970 |
|
971 | JSMapping = (function() {
|
972 | class JSMapping extends Mapping {
|
973 | parse(data) {
|
974 | var _dirname, _filename, _require, code, func;
|
975 | ({code} = require('@babel/core').transform(data, {
|
976 | filename: this.filename,
|
977 | plugins: [
|
978 | [
|
979 | require.resolve('@babel/plugin-transform-react-jsx'),
|
980 | {
|
981 | useBuiltIns: true,
|
982 | pragma: 'preact.h',
|
983 | pragmaFrag: 'preact.Fragment',
|
984 | throwIfNamespace: false
|
985 | }
|
986 | ],
|
987 | implicitFinalReturn
|
988 | ],
|
989 | sourceMaps: 'inline',
|
990 | retainLines: true
|
991 | }));
|
992 |
|
993 |
|
994 |
|
995 | _filename = path.resolve(this.filename);
|
996 | _dirname = path.dirname(_filename);
|
997 |
|
998 | _require = function(module) {
|
999 | if (module.startsWith('.')) {
|
1000 | return require(path.resolve(_dirname, module));
|
1001 | } else {
|
1002 | return require(module);
|
1003 | }
|
1004 | };
|
1005 |
|
1006 |
|
1007 |
|
1008 |
|
1009 | func = new Function('__filename', '__dirname', 'require', 'svgtiler', 'preact', code);
|
1010 | return this.load(func(_filename, _dirname, _require, svgtiler, (0 <= code.indexOf('preact') ? require('preact') : void 0)));
|
1011 | }
|
1012 |
|
1013 | };
|
1014 |
|
1015 | JSMapping.title = "JavaScript mapping file (including JSX notation)";
|
1016 |
|
1017 | JSMapping.help = "Object mapping symbol names to SYMBOL e.g. {dot: 'dot.svg'}";
|
1018 |
|
1019 | return JSMapping;
|
1020 |
|
1021 | }).call(this);
|
1022 |
|
1023 | CoffeeMapping = (function() {
|
1024 | class CoffeeMapping extends JSMapping {
|
1025 | parse(data) {
|
1026 | return super.parse(require('coffeescript').compile(data, {
|
1027 | bare: true,
|
1028 | filename: this.filename,
|
1029 | sourceFiles: [this.filename],
|
1030 | inlineMap: true
|
1031 | }));
|
1032 | }
|
1033 |
|
1034 | };
|
1035 |
|
1036 | CoffeeMapping.title = "CoffeeScript mapping file (including JSX notation)";
|
1037 |
|
1038 | CoffeeMapping.help = "Object mapping symbol names to SYMBOL e.g. dot: 'dot.svg'";
|
1039 |
|
1040 | return CoffeeMapping;
|
1041 |
|
1042 | }).call(this);
|
1043 |
|
1044 |
|
1045 |
|
1046 |
|
1047 |
|
1048 |
|
1049 |
|
1050 |
|
1051 |
|
1052 |
|
1053 |
|
1054 |
|
1055 |
|
1056 |
|
1057 |
|
1058 |
|
1059 |
|
1060 |
|
1061 | Mappings = class Mappings {
|
1062 | constructor(maps = []) {
|
1063 | this.maps = maps;
|
1064 | }
|
1065 |
|
1066 | push(map) {
|
1067 | return this.maps.push(map);
|
1068 | }
|
1069 |
|
1070 | lookup(key) {
|
1071 | var i, k, ref, value;
|
1072 | if (!this.maps.length) {
|
1073 | return;
|
1074 | }
|
1075 | for (i = k = ref = this.maps.length - 1; (ref <= 0 ? k <= 0 : k >= 0); i = ref <= 0 ? ++k : --k) {
|
1076 | value = this.maps[i].lookup(key);
|
1077 | if (value != null) {
|
1078 | return value;
|
1079 | }
|
1080 | }
|
1081 | return void 0;
|
1082 | }
|
1083 |
|
1084 | };
|
1085 |
|
1086 | blankCells = {
|
1087 | '': true,
|
1088 | ' ': true
|
1089 | };
|
1090 |
|
1091 | allBlank = function(list) {
|
1092 | var k, len, x;
|
1093 | for (k = 0, len = list.length; k < len; k++) {
|
1094 | x = list[k];
|
1095 | if ((x != null) && !(x in blankCells)) {
|
1096 | return false;
|
1097 | }
|
1098 | }
|
1099 | return true;
|
1100 | };
|
1101 |
|
1102 | Drawing = (function() {
|
1103 | class Drawing extends Input {
|
1104 | static hrefAttr() {
|
1105 | if (this.useHref) {
|
1106 | return 'href';
|
1107 | } else {
|
1108 | return 'xlink:href';
|
1109 | }
|
1110 | }
|
1111 |
|
1112 | load(data) {
|
1113 | var cell, j, k, l, len, len1, row;
|
1114 |
|
1115 | data = (function() {
|
1116 | var k, len, results;
|
1117 | results = [];
|
1118 | for (k = 0, len = data.length; k < len; k++) {
|
1119 | row = data[k];
|
1120 | results.push((function() {
|
1121 | var l, len1, results1;
|
1122 | results1 = [];
|
1123 | for (l = 0, len1 = row.length; l < len1; l++) {
|
1124 | cell = row[l];
|
1125 | results1.push(cell);
|
1126 | }
|
1127 | return results1;
|
1128 | })());
|
1129 | }
|
1130 | return results;
|
1131 | })();
|
1132 | if (!Drawing.keepMargins) {
|
1133 |
|
1134 | while (data.length > 0 && allBlank(data[0])) {
|
1135 | data.shift();
|
1136 | }
|
1137 |
|
1138 | while (data.length > 0 && allBlank(data[data.length - 1])) {
|
1139 | data.pop();
|
1140 | }
|
1141 | if (data.length > 0) {
|
1142 |
|
1143 | while (allBlank((function() {
|
1144 | var l, len1, results;
|
1145 | results = [];
|
1146 | for (l = 0, len1 = data.length; l < len1; l++) {
|
1147 | row = data[l];
|
1148 | results.push(row[0]);
|
1149 | }
|
1150 | return results;
|
1151 | })())) {
|
1152 | for (k = 0, len = data.length; k < len; k++) {
|
1153 | row = data[k];
|
1154 | row.shift();
|
1155 | }
|
1156 | }
|
1157 |
|
1158 | j = Math.max(...((function() {
|
1159 | var l, len1, results;
|
1160 | results = [];
|
1161 | for (l = 0, len1 = data.length; l < len1; l++) {
|
1162 | row = data[l];
|
1163 | results.push(row.length);
|
1164 | }
|
1165 | return results;
|
1166 | })()));
|
1167 | while (j >= 0 && allBlank((function() {
|
1168 | var len2, n, results;
|
1169 | results = [];
|
1170 | for (n = 0, len2 = data.length; n < len2; n++) {
|
1171 | row = data[n];
|
1172 | results.push(row[j]);
|
1173 | }
|
1174 | return results;
|
1175 | })())) {
|
1176 | for (l = 0, len1 = data.length; l < len1; l++) {
|
1177 | row = data[l];
|
1178 | if (j < row.length) {
|
1179 | row.pop();
|
1180 | }
|
1181 | }
|
1182 | j--;
|
1183 | }
|
1184 | }
|
1185 | }
|
1186 | return this.data = data;
|
1187 | }
|
1188 |
|
1189 | writeSVG(mappings, styles, filename) {
|
1190 |
|
1191 | if (filename == null) {
|
1192 | filename = path.parse(this.filename);
|
1193 | if (filename.ext === '.svg') {
|
1194 | filename.base += '.svg';
|
1195 | } else {
|
1196 | filename.base = filename.base.slice(0, -filename.ext.length) + '.svg';
|
1197 | }
|
1198 | filename = path.format(filename);
|
1199 | }
|
1200 | console.log('->', filename);
|
1201 | fs.writeFileSync(filename, this.renderSVG(mappings, styles));
|
1202 | return filename;
|
1203 | }
|
1204 |
|
1205 | renderSVGDOM(mappings, styles) {
|
1206 | var cell, colWidths, coordsRow, doc, dx, dy, i, inlineImageVersions, inlineImages, j, k, key, l, lastSymbol, len, len1, len2, len3, len4, len5, level, levelOrder, levels, missing, n, name, node, o, p, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, row, row2, rowHeight, scaleX, scaleY, style, styleTag, svg, symbol, symbolsByKey, use, viewBox, x, y;
|
1207 | |
1208 |
|
1209 |
|
1210 |
|
1211 |
|
1212 |
|
1213 | DynamicSymbol.resetAll();
|
1214 | doc = domImplementation.createDocument(SVGNS, 'svg');
|
1215 | svg = doc.documentElement;
|
1216 | if (!Drawing.useHref) {
|
1217 | svg.setAttribute('xmlns:xlink', XLINKNS);
|
1218 | }
|
1219 | svg.setAttribute('version', '1.1');
|
1220 | ref1 = (ref = styles != null ? styles.styles : void 0) != null ? ref : [];
|
1221 |
|
1222 |
|
1223 | for (k = 0, len = ref1.length; k < len; k++) {
|
1224 | style = ref1[k];
|
1225 | svg.appendChild(styleTag = doc.createElementNS(SVGNS, 'style'));
|
1226 | styleTag.textContent = style.css;
|
1227 | }
|
1228 |
|
1229 | missing = {};
|
1230 | this.symbols = (function() {
|
1231 | var l, len1, ref2, results;
|
1232 | ref2 = this.data;
|
1233 | results = [];
|
1234 | for (l = 0, len1 = ref2.length; l < len1; l++) {
|
1235 | row = ref2[l];
|
1236 | results.push((function() {
|
1237 | var len2, n, results1;
|
1238 | results1 = [];
|
1239 | for (n = 0, len2 = row.length; n < len2; n++) {
|
1240 | cell = row[n];
|
1241 | symbol = mappings.lookup(cell);
|
1242 | if (symbol != null) {
|
1243 | results1.push(lastSymbol = symbol);
|
1244 | } else {
|
1245 | missing[cell] = true;
|
1246 | results1.push(unrecognizedSymbol);
|
1247 | }
|
1248 | }
|
1249 | return results1;
|
1250 | })());
|
1251 | }
|
1252 | return results;
|
1253 | }).call(this);
|
1254 | missing = (function() {
|
1255 | var results;
|
1256 | results = [];
|
1257 | for (key in missing) {
|
1258 | if (!hasProp.call(missing, key)) continue;
|
1259 | results.push(`'${key}'`);
|
1260 | }
|
1261 | return results;
|
1262 | })();
|
1263 | if (missing.length) {
|
1264 | console.warn("Failed to recognize symbols:", missing.join(', '));
|
1265 | }
|
1266 |
|
1267 | symbolsByKey = {};
|
1268 | this.symbols = (function() {
|
1269 | var l, len1, ref2, results;
|
1270 | ref2 = this.symbols;
|
1271 | results = [];
|
1272 | for (i = l = 0, len1 = ref2.length; l < len1; i = ++l) {
|
1273 | row = ref2[i];
|
1274 | results.push((function() {
|
1275 | var len2, n, results1;
|
1276 | results1 = [];
|
1277 | for (j = n = 0, len2 = row.length; n < len2; j = ++n) {
|
1278 | symbol = row[j];
|
1279 | if (symbol.usesContext) {
|
1280 | symbol = symbol.use(new Context(this, i, j));
|
1281 | } else {
|
1282 | symbol = symbol.use();
|
1283 | }
|
1284 | if (!(symbol.key in symbolsByKey)) {
|
1285 | symbolsByKey[symbol.key] = symbol;
|
1286 | } else if (symbolsByKey[symbol.key] === !symbol) {
|
1287 | console.warn(`Multiple symbols with key ${symbol.key}`);
|
1288 | }
|
1289 | results1.push(symbol);
|
1290 | }
|
1291 | return results1;
|
1292 | }).call(this));
|
1293 | }
|
1294 | return results;
|
1295 | }).call(this);
|
1296 |
|
1297 | for (key in symbolsByKey) {
|
1298 | symbol = symbolsByKey[key];
|
1299 | if (symbol == null) {
|
1300 | continue;
|
1301 | }
|
1302 | svg.appendChild(symbol.xml.documentElement.cloneNode(true));
|
1303 | }
|
1304 |
|
1305 | inlineImages = {};
|
1306 | inlineImageVersions = {};
|
1307 | domRecurse(svg, function(node, parent) {
|
1308 | var attr, attributes, filename, height, href, l, len1, ref2, ref3, use, version, width;
|
1309 | if (node.nodeName !== 'image') {
|
1310 | return true;
|
1311 | }
|
1312 | ({href} = getHref(node));
|
1313 | if (!(href != null ? href.startsWith('data:') : void 0)) {
|
1314 | return true;
|
1315 | }
|
1316 |
|
1317 |
|
1318 |
|
1319 | filename = (ref2 = node.getAttribute('data-filename')) != null ? ref2 : '';
|
1320 | node.removeAttribute('data-filename');
|
1321 | width = node.getAttribute('data-width');
|
1322 | node.removeAttribute('data-width');
|
1323 | height = node.getAttribute('data-height');
|
1324 | node.removeAttribute('data-height');
|
1325 |
|
1326 | parent.replaceChild((use = doc.createElementNS(SVGNS, 'use')), node);
|
1327 | ref3 = ['x', 'y', 'width', 'height'];
|
1328 | for (l = 0, len1 = ref3.length; l < len1; l++) {
|
1329 | attr = ref3[l];
|
1330 | if (node.hasAttribute(attr)) {
|
1331 | use.setAttribute(attr, node.getAttribute(attr));
|
1332 | }
|
1333 | node.removeAttribute(attr);
|
1334 | }
|
1335 |
|
1336 | attributes = (function() {
|
1337 | var len2, n, ref4, results;
|
1338 | ref4 = node.attributes;
|
1339 | results = [];
|
1340 | for (n = 0, len2 = ref4.length; n < len2; n++) {
|
1341 | attr = ref4[n];
|
1342 | results.push(`${attr.name}=${attr.value}`);
|
1343 | }
|
1344 | return results;
|
1345 | })();
|
1346 | attributes.sort();
|
1347 | attributes = attributes.join(' ');
|
1348 | if (!(attributes in inlineImages)) {
|
1349 | if (inlineImageVersions[filename] == null) {
|
1350 | inlineImageVersions[filename] = 0;
|
1351 | }
|
1352 | version = inlineImageVersions[filename]++;
|
1353 | inlineImages[attributes] = `_image_${escapeId(filename)}_v${version}`;
|
1354 | svg.appendChild(symbol = doc.createElementNS(SVGNS, 'symbol'));
|
1355 | symbol.setAttribute('id', inlineImages[attributes]);
|
1356 |
|
1357 |
|
1358 | node.setAttribute('width', width || use.getAttribute('width'));
|
1359 | node.setAttribute('height', height || use.getAttribute('height'));
|
1360 | symbol.setAttribute('viewBox', `0 0 ${width} ${height}`);
|
1361 | symbol.appendChild(node);
|
1362 | }
|
1363 | use.setAttribute(Drawing.hrefAttr(), '#' + inlineImages[attributes]);
|
1364 | return false;
|
1365 | });
|
1366 |
|
1367 | viewBox = [
|
1368 | 0,
|
1369 | 0,
|
1370 | 0,
|
1371 | 0
|
1372 | ];
|
1373 | levels = {};
|
1374 | y = 0;
|
1375 | colWidths = {};
|
1376 | this.coords = [];
|
1377 | ref2 = this.symbols;
|
1378 | for (i = l = 0, len1 = ref2.length; l < len1; i = ++l) {
|
1379 | row = ref2[i];
|
1380 | this.coords.push(coordsRow = []);
|
1381 | rowHeight = 0;
|
1382 | for (n = 0, len2 = row.length; n < len2; n++) {
|
1383 | symbol = row[n];
|
1384 | if (!symbol.autoHeight) {
|
1385 | if (symbol.height > rowHeight) {
|
1386 | rowHeight = symbol.height;
|
1387 | }
|
1388 | }
|
1389 | }
|
1390 | x = 0;
|
1391 | for (j = o = 0, len3 = row.length; o < len3; j = ++o) {
|
1392 | symbol = row[j];
|
1393 | coordsRow.push({x, y});
|
1394 | if (symbol == null) {
|
1395 | continue;
|
1396 | }
|
1397 | if (levels[name = symbol.zIndex] == null) {
|
1398 | levels[name] = [];
|
1399 | }
|
1400 | levels[symbol.zIndex].push(use = doc.createElementNS(SVGNS, 'use'));
|
1401 | use.setAttribute(Drawing.hrefAttr(), '#' + symbol.id);
|
1402 | use.setAttribute('x', x);
|
1403 | use.setAttribute('y', y);
|
1404 | scaleX = scaleY = 1;
|
1405 | if (symbol.autoWidth) {
|
1406 | if (colWidths[j] == null) {
|
1407 | colWidths[j] = Math.max(0, ...((function() {
|
1408 | var len4, p, ref3, results;
|
1409 | ref3 = this.symbols;
|
1410 | results = [];
|
1411 | for (p = 0, len4 = ref3.length; p < len4; p++) {
|
1412 | row2 = ref3[p];
|
1413 | if ((row2[j] != null) && !row2[j].autoWidth) {
|
1414 | results.push(row2[j].width);
|
1415 | }
|
1416 | }
|
1417 | return results;
|
1418 | }).call(this)));
|
1419 | }
|
1420 | if (symbol.width !== 0) {
|
1421 | scaleX = colWidths[j] / symbol.width;
|
1422 | }
|
1423 | if (!symbol.autoHeight) {
|
1424 | scaleY = scaleX;
|
1425 | }
|
1426 | }
|
1427 | if (symbol.autoHeight) {
|
1428 | if (symbol.height !== 0) {
|
1429 | scaleY = rowHeight / symbol.height;
|
1430 | }
|
1431 | if (!symbol.autoWidth) {
|
1432 | scaleX = scaleY;
|
1433 | }
|
1434 | }
|
1435 |
|
1436 |
|
1437 | use.setAttribute('width', ((ref3 = (ref4 = symbol.viewBox) != null ? ref4[2] : void 0) != null ? ref3 : symbol.width) * scaleX);
|
1438 | use.setAttribute('height', ((ref5 = (ref6 = symbol.viewBox) != null ? ref6[3] : void 0) != null ? ref5 : symbol.height) * scaleY);
|
1439 | if (symbol.overflowBox != null) {
|
1440 | dx = (symbol.overflowBox[0] - symbol.viewBox[0]) * scaleX;
|
1441 | dy = (symbol.overflowBox[1] - symbol.viewBox[1]) * scaleY;
|
1442 | viewBox[0] = Math.min(viewBox[0], x + dx);
|
1443 | viewBox[1] = Math.min(viewBox[1], y + dy);
|
1444 | viewBox[2] = Math.max(viewBox[2], x + dx + symbol.overflowBox[2] * scaleX);
|
1445 | viewBox[3] = Math.max(viewBox[3], y + dy + symbol.overflowBox[3] * scaleY);
|
1446 | }
|
1447 | x += symbol.width * scaleX;
|
1448 | viewBox[2] = Math.max(viewBox[2], x);
|
1449 | }
|
1450 | y += rowHeight;
|
1451 | viewBox[3] = Math.max(viewBox[3], y);
|
1452 | }
|
1453 |
|
1454 | viewBox[2] = viewBox[2] - viewBox[0];
|
1455 | viewBox[3] = viewBox[3] - viewBox[1];
|
1456 |
|
1457 | levelOrder = ((function() {
|
1458 | var results;
|
1459 | results = [];
|
1460 | for (level in levels) {
|
1461 | results.push(level);
|
1462 | }
|
1463 | return results;
|
1464 | })()).sort(function(x, y) {
|
1465 | return x - y;
|
1466 | });
|
1467 | for (p = 0, len4 = levelOrder.length; p < len4; p++) {
|
1468 | level = levelOrder[p];
|
1469 | ref7 = levels[level];
|
1470 | for (q = 0, len5 = ref7.length; q < len5; q++) {
|
1471 | node = ref7[q];
|
1472 | svg.appendChild(node);
|
1473 | }
|
1474 | }
|
1475 | svg.setAttribute('viewBox', viewBox.join(' '));
|
1476 | svg.setAttribute('width', this.width = viewBox[2]);
|
1477 | svg.setAttribute('height', this.height = viewBox[3]);
|
1478 |
|
1479 | return doc;
|
1480 | }
|
1481 |
|
1482 | renderSVG(mappings, styles) {
|
1483 | var out;
|
1484 | out = new XMLSerializer().serializeToString(this.renderSVGDOM(mappings, styles));
|
1485 |
|
1486 |
|
1487 | out = out.replace(/\sxmlns:xlink=""/g, '');
|
1488 | if (prettyXML != null) {
|
1489 | out = prettyXML(out, {
|
1490 | newline: '\n'
|
1491 | });
|
1492 | }
|
1493 | return `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
1494 | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
1495 | ` + out;
|
1496 | }
|
1497 |
|
1498 | renderTeX(filename) {
|
1499 | var anchor, basename, child, content, i, j, k, l, len, len1, len2, lines, n, ref, ref1, ref2, ref3, row, symbol, text, tx, ty, wrap, x, y;
|
1500 |
|
1501 | filename = path.parse(filename);
|
1502 | basename = filename.base.slice(0, -filename.ext.length);
|
1503 |
|
1504 |
|
1505 | lines = [
|
1506 | `%% Creator: svgtiler ${metadata.version}, https://github.com/edemaine/svgtiler
|
1507 | %% This LaTeX file includes and overlays text on top of companion file
|
1508 | %% ${basename}.pdf/.png
|
1509 | %%
|
1510 | %% Instead of \\includegraphics, include this figure via
|
1511 | %% \\input{${filename.base}}
|
1512 | %% You can scale the image by first defining \\svg{width,height,scale}:
|
1513 | %% \\def\\svgwidth{\\linewidth} % full width
|
1514 | %% or
|
1515 | %% \\def\\svgheight{5in}
|
1516 | %% or
|
1517 | %% \\def\\svgscale{0.5} % 50%
|
1518 | %% (If multiple are specified, the first in the list above takes priority.)
|
1519 | %%
|
1520 | %% If this file resides in another directory from the root .tex file,
|
1521 | %% you need to help it find its auxiliary .pdf/.png file via one of the
|
1522 | %% following options (any one will do):
|
1523 | %% 1. \\usepackage{currfile} so that this file can find its own directory.
|
1524 | %% 2. \\usepackage{import} and \\import{path/to/file/}{${filename.base}}
|
1525 | %% instead of \\import{${filename.base}}
|
1526 | %% 3. \\graphicspath{{path/to/file/}} % note extra braces and trailing slash
|
1527 | %%
|
1528 | \\begingroup
|
1529 | \\providecommand\\color[2][]{%
|
1530 | \\errmessage{You should load package 'color.sty' to render color in svgtiler text.}%
|
1531 | \\renewcommand\\color[2][]{}%
|
1532 | }%
|
1533 | \\ifx\\currfiledir\\undefined
|
1534 | \\def\\currfiledir{}%
|
1535 | \\fi
|
1536 | \\ifx\\svgwidth\\undefined
|
1537 | \\ifx\\svgheight\\undefined
|
1538 | \\unitlength=0.75bp\\relax % 1px (SVG unit) = 0.75bp (SVG pts)
|
1539 | \\ifx\\svgscale\\undefined\\else
|
1540 | \\ifx\\real\\undefined % in case calc.sty not loaded
|
1541 | \\unitlength=\\svgscale \\unitlength
|
1542 | \\else
|
1543 | \\setlength{\\unitlength}{\\unitlength * \\real{\\svgscale}}%
|
1544 | \\fi
|
1545 | \\fi
|
1546 | \\else
|
1547 | \\unitlength=\\svgheight
|
1548 | \\unitlength=${1 / this.height}\\unitlength % divide by image height
|
1549 | \\fi
|
1550 | \\else
|
1551 | \\unitlength=\\svgwidth
|
1552 | \\unitlength=${1 / this.width}\\unitlength % divide by image width
|
1553 | \\fi
|
1554 | \\def\\clap#1{\\hbox to 0pt{\\hss#1\\hss}}%
|
1555 | \\begin{picture}(${this.width},${this.height})%
|
1556 | \\put(0,0){\\includegraphics[width=${this.width}\\unitlength]{\\currfiledir ${basename}}}%`
|
1557 | ];
|
1558 | ref = this.symbols;
|
1559 | for (i = k = 0, len = ref.length; k < len; i = ++k) {
|
1560 | row = ref[i];
|
1561 | for (j = l = 0, len1 = row.length; l < len1; j = ++l) {
|
1562 | symbol = row[j];
|
1563 | ({x, y} = this.coords[i][j]);
|
1564 | ref1 = symbol.text;
|
1565 | for (n = 0, len2 = ref1.length; n < len2; n++) {
|
1566 | text = ref1[n];
|
1567 | tx = (ref2 = parseNum(text.getAttribute('x'))) != null ? ref2 : 0;
|
1568 | ty = (ref3 = parseNum(text.getAttribute('y'))) != null ? ref3 : 0;
|
1569 | content = ((function() {
|
1570 | var len3, o, ref4, results;
|
1571 | ref4 = text.childNodes;
|
1572 | // TEXT_NODE
|
1573 | results = [];
|
1574 | for (o = 0, len3 = ref4.length; o < len3; o++) {
|
1575 | child = ref4[o];
|
1576 | if (child.nodeType === 3) {
|
1577 | results.push(child.data);
|
1578 | }
|
1579 | }
|
1580 | return results;
|
1581 | })()).join('');
|
1582 | anchor = attributeOrStyle(text, 'text-anchor');
|
1583 | if (/^middle\b/.test(anchor)) {
|
1584 | wrap = '\\clap{';
|
1585 | } else if (/^end\b/.test(anchor)) {
|
1586 | wrap = '\\rlap{'; //if /^start\b/.test anchor # default
|
1587 | } else {
|
1588 | wrap = '\\llap{';
|
1589 | }
|
1590 | // "@height -" is to flip between y down (SVG) and y up (picture)
|
1591 | lines.push(` \\put(${x + tx},${this.height - (y + ty)}){\\color{${attributeOrStyle(text, 'fill') || 'black'}}${wrap}${content}${wrap && '}'}}%`);
|
1592 | }
|
1593 | }
|
1594 | }
|
1595 | lines.push(` \\end{picture}%
|
1596 | \\endgroup`, ''); // trailing newline
|
1597 | return lines.join('\n');
|
1598 | }
|
1599 |
|
1600 | writeTeX(filename) {
|
1601 | /*
|
1602 | Must be called *after* `writeSVG`.
|
1603 | Default filename is the input filename with extension replaced by .svg_tex
|
1604 | (analogous to .pdf_tex from Inkscape's --export-latex feature, but noting
|
1605 | that the text is extracted from the SVG not the PDF, and that this file
|
1606 | works with both .pdf and .png auxiliary files).
|
1607 | */
|
1608 | if (filename == null) {
|
1609 | filename = path.parse(this.filename);
|
1610 | if (filename.ext === '.svg_tex') {
|
1611 | filename.base += '.svg_tex';
|
1612 | } else {
|
1613 | filename.base = filename.base.slice(0, -filename.ext.length) + '.svg_tex';
|
1614 | }
|
1615 | filename = path.format(filename);
|
1616 | }
|
1617 | console.log(' &', filename);
|
1618 | fs.writeFileSync(filename, this.renderTeX(filename));
|
1619 | return filename;
|
1620 | }
|
1621 |
|
1622 | };
|
1623 |
|
1624 | Drawing.inlineImages = typeof window === "undefined" || window === null;
|
1625 |
|
1626 | return Drawing;
|
1627 |
|
1628 | }).call(this);
|
1629 |
|
1630 | ASCIIDrawing = (function() {
|
1631 | class ASCIIDrawing extends Drawing {
|
1632 | parse(data) {
|
1633 | var line;
|
1634 | return this.load((function() {
|
1635 | var k, len, ref, results;
|
1636 | ref = splitIntoLines(data);
|
1637 | results = [];
|
1638 | for (k = 0, len = ref.length; k < len; k++) {
|
1639 | line = ref[k];
|
1640 | results.push(graphemeSplitter.splitGraphemes(line));
|
1641 | }
|
1642 | return results;
|
1643 | })());
|
1644 | }
|
1645 |
|
1646 | };
|
1647 |
|
1648 | ASCIIDrawing.title = "ASCII drawing (one character per symbol)";
|
1649 |
|
1650 | return ASCIIDrawing;
|
1651 |
|
1652 | }).call(this);
|
1653 |
|
1654 | DSVDrawing = class DSVDrawing extends Drawing {
|
1655 | parse(data) {
|
1656 | var ref;
|
1657 | //# Remove trailing newline / final blank line.
|
1658 | if (data.slice(-2) === '\r\n') {
|
1659 | data = data.slice(0, -2);
|
1660 | } else if ((ref = data.slice(-1)) === '\r' || ref === '\n') {
|
1661 | data = data.slice(0, -1);
|
1662 | }
|
1663 | //# CSV parser.
|
1664 | return this.load(require('csv-parse/lib/sync')(data, {
|
1665 | delimiter: this.constructor.delimiter,
|
1666 | relax_column_count: true
|
1667 | }));
|
1668 | }
|
1669 |
|
1670 | };
|
1671 |
|
1672 | SSVDrawing = (function() {
|
1673 | class SSVDrawing extends DSVDrawing {
|
1674 | parse(data) {
|
1675 | //# Coallesce non-newline whitespace into single space
|
1676 | return super.parse(data.replace(/[ \t\f\v]+/g, ' '));
|
1677 | }
|
1678 |
|
1679 | };
|
1680 |
|
1681 | SSVDrawing.title = "Space-delimiter drawing (one word per symbol)";
|
1682 |
|
1683 | SSVDrawing.delimiter = ' ';
|
1684 |
|
1685 | return SSVDrawing;
|
1686 |
|
1687 | }).call(this);
|
1688 |
|
1689 | CSVDrawing = (function() {
|
1690 | class CSVDrawing extends DSVDrawing {};
|
1691 |
|
1692 | CSVDrawing.title = "Comma-separated drawing (spreadsheet export)";
|
1693 |
|
1694 | CSVDrawing.delimiter = ',';
|
1695 |
|
1696 | return CSVDrawing;
|
1697 |
|
1698 | }).call(this);
|
1699 |
|
1700 | TSVDrawing = (function() {
|
1701 | class TSVDrawing extends DSVDrawing {};
|
1702 |
|
1703 | TSVDrawing.title = "Tab-separated drawing (spreadsheet export)";
|
1704 |
|
1705 | TSVDrawing.delimiter = '\t';
|
1706 |
|
1707 | return TSVDrawing;
|
1708 |
|
1709 | }).call(this);
|
1710 |
|
1711 | Drawings = (function() {
|
1712 | class Drawings extends Input {
|
1713 | load(datas) {
|
1714 | var data, drawing;
|
1715 | return this.drawings = (function() {
|
1716 | var k, len, results;
|
1717 | results = [];
|
1718 | for (k = 0, len = datas.length; k < len; k++) {
|
1719 | data = datas[k];
|
1720 | drawing = new Drawing();
|
1721 | drawing.filename = this.filename;
|
1722 | drawing.subname = data.subname;
|
1723 | drawing.load(data);
|
1724 | results.push(drawing);
|
1725 | }
|
1726 | return results;
|
1727 | }).call(this);
|
1728 | }
|
1729 |
|
1730 | subfilename(extension, drawing) {
|
1731 | var filename2;
|
1732 | filename2 = path.parse(this.filename);
|
1733 | filename2.base = filename2.base.slice(0, -filename2.ext.length);
|
1734 | if (this.drawings.length > 1) {
|
1735 | filename2.base += this.constructor.filenameSeparator + drawing.subname;
|
1736 | }
|
1737 | filename2.base += extension;
|
1738 | return path.format(filename2);
|
1739 | }
|
1740 |
|
1741 | writeSVG(mappings, styles, filename) {
|
1742 | var drawing, k, len, ref, results;
|
1743 | ref = this.drawings;
|
1744 | results = [];
|
1745 | for (k = 0, len = ref.length; k < len; k++) {
|
1746 | drawing = ref[k];
|
1747 | results.push(drawing.writeSVG(mappings, styles, this.subfilename('.svg', drawing)));
|
1748 | }
|
1749 | return results;
|
1750 | }
|
1751 |
|
1752 | writeTeX(filename) {
|
1753 | var drawing, k, len, ref, results;
|
1754 | ref = this.drawings;
|
1755 | results = [];
|
1756 | for (k = 0, len = ref.length; k < len; k++) {
|
1757 | drawing = ref[k];
|
1758 | results.push(drawing.writeTeX(this.subfilename('.svg_tex', drawing)));
|
1759 | }
|
1760 | return results;
|
1761 | }
|
1762 |
|
1763 | };
|
1764 |
|
1765 | Drawings.filenameSeparator = '_';
|
1766 |
|
1767 | return Drawings;
|
1768 |
|
1769 | }).call(this);
|
1770 |
|
1771 | XLSXDrawings = (function() {
|
1772 | class XLSXDrawings extends Drawings {
|
1773 | parse(data) {
|
1774 | var rows, sheet, sheetInfo, subname, workbook, xlsx;
|
1775 | xlsx = require('xlsx');
|
1776 | workbook = xlsx.read(data, {
|
1777 | type: 'binary'
|
1778 | });
|
1779 | //# https://www.npmjs.com/package/xlsx#common-spreadsheet-format
|
1780 | return this.load((function() {
|
1781 | var k, len, ref, results;
|
1782 | ref = workbook.Workbook.Sheets;
|
1783 | results = [];
|
1784 | for (k = 0, len = ref.length; k < len; k++) {
|
1785 | sheetInfo = ref[k];
|
1786 | subname = sheetInfo.name;
|
1787 | sheet = workbook.Sheets[subname];
|
1788 | //# 0 = Visible, 1 = Hidden, 2 = Very Hidden
|
1789 | //# https://sheetjs.gitbooks.io/docs/#sheet-visibility
|
1790 | if (sheetInfo.Hidden && !Drawings.keepHidden) {
|
1791 | continue;
|
1792 | }
|
1793 | if (subname.length === 31) {
|
1794 | console.warn(`Warning: Sheet '${subname}' has length exactly 31, which may be caused by Google Sheets export truncation`);
|
1795 | }
|
1796 | rows = xlsx.utils.sheet_to_json(sheet, {
|
1797 | header: 1,
|
1798 | defval: ''
|
1799 | });
|
1800 | rows.subname = subname;
|
1801 | results.push(rows);
|
1802 | }
|
1803 | return results;
|
1804 | })());
|
1805 | }
|
1806 |
|
1807 | };
|
1808 |
|
1809 | XLSXDrawings.encoding = 'binary';
|
1810 |
|
1811 | XLSXDrawings.title = "Spreadsheet drawing(s) (Excel/OpenDocument/Lotus/dBASE)";
|
1812 |
|
1813 | return XLSXDrawings;
|
1814 |
|
1815 | }).call(this);
|
1816 |
|
1817 | Context = class Context {
|
1818 | constructor(drawing1, i1, j1) {
|
1819 | var ref, ref1;
|
1820 | this.drawing = drawing1;
|
1821 | this.i = i1;
|
1822 | this.j = j1;
|
1823 | this.symbols = this.drawing.symbols;
|
1824 | this.filename = this.drawing.filename;
|
1825 | this.subname = this.drawing.subname;
|
1826 | this.symbol = (ref = this.symbols[this.i]) != null ? ref[this.j] : void 0;
|
1827 | this.key = (ref1 = this.symbol) != null ? ref1.key : void 0;
|
1828 | }
|
1829 |
|
1830 | neighbor(dj, di) {
|
1831 | return new Context(this.drawing, this.i + di, this.j + dj);
|
1832 | }
|
1833 |
|
1834 | includes(...args) {
|
1835 | return (this.symbol != null) && this.symbol.includes(...args);
|
1836 | }
|
1837 |
|
1838 | row(di = 0) {
|
1839 | var i, j, k, len, ref, ref1, results, symbol;
|
1840 | i = this.i + di;
|
1841 | ref1 = (ref = this.symbols[i]) != null ? ref : [];
|
1842 | results = [];
|
1843 | for (j = k = 0, len = ref1.length; k < len; j = ++k) {
|
1844 | symbol = ref1[j];
|
1845 | results.push(new Context(this.drawing, i, j));
|
1846 | }
|
1847 | return results;
|
1848 | }
|
1849 |
|
1850 | column(dj = 0) {
|
1851 | var i, j, k, len, ref, results, row;
|
1852 | j = this.j + dj;
|
1853 | ref = this.symbols;
|
1854 | results = [];
|
1855 | for (i = k = 0, len = ref.length; k < len; i = ++k) {
|
1856 | row = ref[i];
|
1857 | results.push(new Context(this.drawing, i, j));
|
1858 | }
|
1859 | return results;
|
1860 | }
|
1861 |
|
1862 | };
|
1863 |
|
1864 | extensionMap = {
|
1865 | // Mappings
|
1866 | '.txt': ASCIIMapping,
|
1867 | '.js': JSMapping,
|
1868 | '.jsx': JSMapping,
|
1869 | '.coffee': CoffeeMapping,
|
1870 | '.cjsx': CoffeeMapping,
|
1871 | // Drawings
|
1872 | '.asc': ASCIIDrawing,
|
1873 | '.ssv': SSVDrawing,
|
1874 | '.csv': CSVDrawing,
|
1875 | '.tsv': TSVDrawing,
|
1876 | //# Parsable by xlsx package:
|
1877 | '.xlsx': XLSXDrawings, //# Excel 2007+ XML Format
|
1878 | '.xlsm': XLSXDrawings, //# Excel 2007+ Macro XML Format
|
1879 | '.xlsb': XLSXDrawings, //# Excel 2007+ Binary Format
|
1880 | '.xls': XLSXDrawings, //# Excel 2.0 or 2003-2004 (SpreadsheetML)
|
1881 | '.ods': XLSXDrawings, //# OpenDocument Spreadsheet
|
1882 | '.fods': XLSXDrawings, //# Flat OpenDocument Spreadsheet
|
1883 | '.dif': XLSXDrawings, //# Data Interchange Format (DIF)
|
1884 | '.prn': XLSXDrawings, //# Lotus Formatted Text
|
1885 | '.dbf': XLSXDrawings, //# dBASE II/III/IV / Visual FoxPro
|
1886 | // Styles
|
1887 | '.css': CSSStyle,
|
1888 | '.styl': StylusStyle
|
1889 | };
|
1890 |
|
1891 | sanitize = true;
|
1892 |
|
1893 | bufferSize = 16 * 1024;
|
1894 |
|
1895 | postprocess = function(format, filename) {
|
1896 | var buffer, e, file, fileSize, match, position, readSize, string;
|
1897 | if (!sanitize) {
|
1898 | return;
|
1899 | }
|
1900 | try {
|
1901 | switch (format) {
|
1902 | case 'pdf':
|
1903 | //# Blank out /CreationDate in PDF for easier version control.
|
1904 | //# Replace these commands with spaces to avoid in-file pointer errors.
|
1905 | buffer = Buffer.alloc(bufferSize);
|
1906 | fileSize = fs.statSync(filename).size;
|
1907 | position = Math.max(0, fileSize - bufferSize);
|
1908 | file = fs.openSync(filename, 'r+');
|
1909 | readSize = fs.readSync(file, buffer, 0, bufferSize, position);
|
1910 | string = buffer.toString('binary'); //# must use single-byte encoding!
|
1911 | match = /\/CreationDate\s*\((?:[^()\\]|\\[^])*\)/.exec(string);
|
1912 | if (match != null) {
|
1913 | fs.writeSync(file, ' '.repeat(match[0].length), position + match.index);
|
1914 | }
|
1915 | return fs.closeSync(file);
|
1916 | }
|
1917 | } catch (error1) {
|
1918 | e = error1;
|
1919 | return console.log(`Failed to postprocess '${filename}': ${e}`);
|
1920 | }
|
1921 | };
|
1922 |
|
1923 | inkscapeVersion = null;
|
1924 |
|
1925 | convertSVG = function(format, svg, sync) {
|
1926 | var args, child_process, filename, output, preprocess, result;
|
1927 | child_process = require('child_process');
|
1928 | if (inkscapeVersion == null) {
|
1929 | result = child_process.spawnSync('inkscape', ['--version']);
|
1930 | if (result.error) {
|
1931 | console.log(`inkscape --version failed: ${result.error.message}`);
|
1932 | } else if (result.status || result.signal) {
|
1933 | console.log(`inkscape --version failed: ${result.stderr.toString()}`);
|
1934 | } else {
|
1935 | inkscapeVersion = result.stdout.toString().replace(/^Inkscape\s*/, '');
|
1936 | }
|
1937 | }
|
1938 | filename = path.parse(svg);
|
1939 | if (filename.ext === `.${format}`) {
|
1940 | filename.base += `.${format}`;
|
1941 | } else {
|
1942 | filename.base = `${filename.base.slice(0, -filename.ext.length)}.${format}`;
|
1943 | }
|
1944 | output = path.format(filename);
|
1945 | //# Workaround relative paths not working in MacOS distribution of Inkscape
|
1946 | //# [https://bugs.launchpad.net/inkscape/+bug/181639]
|
1947 | if (process.platform === 'darwin') {
|
1948 | preprocess = path.resolve;
|
1949 | } else {
|
1950 | preprocess = function(x) {
|
1951 | return x;
|
1952 | };
|
1953 | }
|
1954 | if (inkscapeVersion.startsWith('0')) {
|
1955 | args = ["-z", `--file=${preprocess(svg)}`, `--export-${format}=${preprocess(output)}`];
|
1956 | } else {
|
1957 | args = [
|
1958 | "--export-overwrite",
|
1959 | //"--export-type=#{format}"
|
1960 | `--export-filename=${preprocess(output)}`,
|
1961 | preprocess(svg)
|
1962 | ];
|
1963 | }
|
1964 | if (sync) {
|
1965 | //# In sychronous mode, we let inkscape directly output its error messages,
|
1966 | //# and add warnings about any failures that occur.
|
1967 | console.log('=>', output);
|
1968 | result = child_process.spawnSync('inkscape', args, {
|
1969 | stdio: 'inherit'
|
1970 | });
|
1971 | if (result.error) {
|
1972 | return console.log(result.error.message);
|
1973 | } else if (result.status || result.signal) {
|
1974 | return console.log(`:-( ${output} FAILED`);
|
1975 | } else {
|
1976 | return postprocess(format, output);
|
1977 | }
|
1978 | } else {
|
1979 | //# In asychronous mode, we capture inkscape's outputs, and print them only
|
1980 | //# when the process has finished, along with which file failed, to avoid
|
1981 | //# mixing up messages from parallel executions.
|
1982 | return function(resolve) {
|
1983 | var inkscape, out;
|
1984 | console.log('=>', output);
|
1985 | inkscape = child_process.spawn('inkscape', args);
|
1986 | out = '';
|
1987 | inkscape.stdout.on('data', function(buf) {
|
1988 | return out += buf;
|
1989 | });
|
1990 | inkscape.stderr.on('data', function(buf) {
|
1991 | return out += buf;
|
1992 | });
|
1993 | inkscape.on('error', function(error) {
|
1994 | return console.log(error.message);
|
1995 | });
|
1996 | return inkscape.on('exit', function(status, signal) {
|
1997 | if (status || signal) {
|
1998 | console.log(`:-( ${output} FAILED:`);
|
1999 | console.log(out);
|
2000 | } else {
|
2001 | postprocess(format, output);
|
2002 | }
|
2003 | return resolve();
|
2004 | });
|
2005 | };
|
2006 | }
|
2007 | };
|
2008 |
|
2009 | help = function() {
|
2010 | var extension, klass;
|
2011 | console.log(`svgtiler ${metadata.version}
|
2012 | Usage: ${process.argv[1]} (...options and filenames...)
|
2013 | Documentation: https:
|
2014 |
|
2015 | Optional arguments:
|
2016 | --help Show this help message and exit.
|
2017 | -m / --margin Don't delete blank extreme rows/columns
|
2018 | --hidden Process hidden sheets within spreadsheet files
|
2019 | --tw TILE_WIDTH / --tile-width TILE_WIDTH
|
2020 | Force all symbol tiles to have specified width
|
2021 | --th TILE_HEIGHT / --tile-height TILE_HEIGHT
|
2022 | Force all symbol tiles to have specified height
|
2023 | -p / --pdf Convert output SVG files to PDF via Inkscape
|
2024 | -P / --png Convert output SVG files to PNG via Inkscape
|
2025 | -t / --tex Move <text> from SVG to accompanying LaTeX file.tex
|
2026 | --no-inline Don't inline <image>s into output SVG
|
2027 | --no-overflow Don't default <symbol> overflow to "visible"
|
2028 | --no-sanitize Don't sanitize PDF output by blanking out /CreationDate
|
2029 | -j N / --jobs N Run up to N Inkscape jobs in parallel
|
2030 |
|
2031 | Filename arguments: (mappings before drawings!)
|
2032 | `);
|
2033 | for (extension in extensionMap) {
|
2034 | klass = extensionMap[extension];
|
2035 | if (extension.length < 10) {
|
2036 | extension += ' '.repeat(10 - extension.length);
|
2037 | }
|
2038 | console.log(` *${extension} ${klass.title}`);
|
2039 | if (klass.help != null) {
|
2040 | console.log(` ${klass.help}`);
|
2041 | }
|
2042 | }
|
2043 | console.log(`
|
2044 | SYMBOL specifiers: (omit the quotes in anything except .js and .coffee files)
|
2045 |
|
2046 | 'filename.svg': load SVG from specified file
|
2047 | 'filename.png': include PNG image from specified file
|
2048 | 'filename.jpg': include JPEG image from specified file
|
2049 | '<svg>...</svg>': raw SVG
|
2050 | -> ...@key...: function computing SVG, with \`this\` bound to Context with
|
2051 | \`key\` (symbol name), \`i\` and \`j\` (y and x coordinates),
|
2052 | \`filename\` (drawing filename), \`subname\` (subsheet name),
|
2053 | and supporting \`neighbor\`/\`includes\`/\`row\`/\`column\` methods`);
|
2054 | //object with one or more attributes
|
2055 | return process.exit();
|
2056 | };
|
2057 |
|
2058 | main = function() {
|
2059 | var arg, args, filename, filenames, files, format, formats, i, input, jobs, k, l, len, len1, len2, mappings, n, skip, styles, sync;
|
2060 | mappings = new Mappings();
|
2061 | styles = new Styles();
|
2062 | args = process.argv.slice(2);
|
2063 | files = skip = 0;
|
2064 | formats = [];
|
2065 | jobs = [];
|
2066 | sync = true;
|
2067 | for (i = k = 0, len = args.length; k < len; i = ++k) {
|
2068 | arg = args[i];
|
2069 | if (skip) {
|
2070 | skip--;
|
2071 | continue;
|
2072 | }
|
2073 | switch (arg) {
|
2074 | case '-h':
|
2075 | case '--help':
|
2076 | help();
|
2077 | break;
|
2078 | case '-m':
|
2079 | case '--margin':
|
2080 | Drawing.keepMargins = true;
|
2081 | break;
|
2082 | case '--hidden':
|
2083 | Drawings.keepHidden = true;
|
2084 | break;
|
2085 | case '--tw':
|
2086 | case '--tile-width':
|
2087 | skip = 1;
|
2088 | arg = parseFloat(args[i + 1]);
|
2089 | if (arg) {
|
2090 | Symbol.forceWidth = arg;
|
2091 | } else {
|
2092 | console.warn(`Invalid argument to --tile-width: ${args[i + 1]}`);
|
2093 | }
|
2094 | break;
|
2095 | case '--th':
|
2096 | case '--tile-height':
|
2097 | skip = 1;
|
2098 | arg = parseFloat(args[i + 1]);
|
2099 | if (arg) {
|
2100 | Symbol.forceHeight = arg;
|
2101 | } else {
|
2102 | console.warn(`Invalid argument to --tile-height: ${args[i + 1]}`);
|
2103 | }
|
2104 | break;
|
2105 | case '-p':
|
2106 | case '--pdf':
|
2107 | formats.push('pdf');
|
2108 | break;
|
2109 | case '-P':
|
2110 | case '--png':
|
2111 | formats.push('png');
|
2112 | break;
|
2113 | case '-t':
|
2114 | case '--tex':
|
2115 | Symbol.texText = true;
|
2116 | break;
|
2117 | case '--no-sanitize':
|
2118 | sanitize = false;
|
2119 | break;
|
2120 | case '--no-overflow':
|
2121 | Symbol.overflowDefault = null;
|
2122 | break;
|
2123 | case '--no-inline':
|
2124 | Drawing.inlineImages = false;
|
2125 | break;
|
2126 | case '-j':
|
2127 | case '--jobs':
|
2128 | skip = 1;
|
2129 | arg = parseInt(args[i + 1]);
|
2130 | if (arg) {
|
2131 | jobs = new require('async-limiter')({
|
2132 | concurrency: arg
|
2133 | });
|
2134 | sync = false;
|
2135 | } else {
|
2136 | console.warn(`Invalid argument to --jobs: ${args[i + 1]}`);
|
2137 | }
|
2138 | break;
|
2139 | default:
|
2140 | files++;
|
2141 | console.log('*', arg);
|
2142 | input = Input.recognize(arg);
|
2143 | if (input instanceof Mapping) {
|
2144 | mappings.push(input);
|
2145 | } else if (input instanceof Style) {
|
2146 | styles.push(input);
|
2147 | } else if (input instanceof Drawing || input instanceof Drawings) {
|
2148 | filenames = input.writeSVG(mappings, styles);
|
2149 | if (Symbol.texText) {
|
2150 | input.writeTeX();
|
2151 | }
|
2152 | for (l = 0, len1 = formats.length; l < len1; l++) {
|
2153 | format = formats[l];
|
2154 | if (typeof filenames === 'string') {
|
2155 | jobs.push(convertSVG(format, filenames, sync));
|
2156 | } else {
|
2157 | for (n = 0, len2 = filenames.length; n < len2; n++) {
|
2158 | filename = filenames[n];
|
2159 | jobs.push(convertSVG(format, filename, sync));
|
2160 | }
|
2161 | }
|
2162 | }
|
2163 | }
|
2164 | }
|
2165 | }
|
2166 | if (!files) {
|
2167 | console.log('Not enough filename arguments');
|
2168 | return help();
|
2169 | }
|
2170 | };
|
2171 |
|
2172 | svgtiler = {
|
2173 | Symbol,
|
2174 | StaticSymbol,
|
2175 | DynamicSymbol,
|
2176 | unrecognizedSymbol,
|
2177 | Mapping,
|
2178 | ASCIIMapping,
|
2179 | JSMapping,
|
2180 | CoffeeMapping,
|
2181 | Drawing,
|
2182 | ASCIIDrawing,
|
2183 | DSVDrawing,
|
2184 | SSVDrawing,
|
2185 | CSVDrawing,
|
2186 | TSVDrawing,
|
2187 | Drawings,
|
2188 | XLSXDrawings,
|
2189 | Style,
|
2190 | CSSStyle,
|
2191 | StylusStyle,
|
2192 | extensionMap,
|
2193 | Input,
|
2194 | Mappings,
|
2195 | Context,
|
2196 | SVGTilerException,
|
2197 | SVGNS,
|
2198 | XLINKNS,
|
2199 | escapeId,
|
2200 | main,
|
2201 | convertSVG,
|
2202 | version: metadata.version
|
2203 | };
|
2204 |
|
2205 | if (typeof module !== "undefined" && module !== null) {
|
2206 | module.exports = svgtiler;
|
2207 | }
|
2208 |
|
2209 | if (typeof window !== "undefined" && window !== null) {
|
2210 | window.svgtiler = svgtiler;
|
2211 | }
|
2212 |
|
2213 | if (typeof window === "undefined" || window === null) {
|
2214 | if ((typeof require !== "undefined" && require !== null ? require.main : void 0) === module) {
|
2215 | main();
|
2216 | }
|
2217 | }
|
2218 |
|
2219 | }).call(this);
|