UNPKG

4.83 kBJavaScriptView Raw
1
2const { db } = require('../db/db');
3const { style, swu, convert } = require('@sutton-signwriting/core');
4const fs = require('fs');
5
6/**
7 * Function that creates an SVG image from an SWU sign with an optional style string
8 * @function swu.signSvgBody
9 * @param {string} swuSign - an SWU sign with optional style string
10 * @returns {string} sign svg body
11 * @example
12 * // using promise.then
13 * swu.signSvgBody('𝠃𝤟𝤩񋛩𝣵𝤐񀀒𝤇𝣤񋚥𝤐𝤆񀀚𝣮𝣭').then( svg => {
14 * console.log(svg)
15 * })
16 * @example
17 * // using async/await
18 * const svg = await swu.signSvgBody('𝠃𝤟𝤩񋛩𝣵𝤐񀀒𝤇𝣤񋚥𝤐𝤆񀀚𝣮𝣭')
19 */
20const signSvgBody = async (swuSign) => {
21 let parsed = swu.parse.sign(swuSign);
22 const blank = '';
23 if (!parsed.spatials) return blank;
24 const symlist = parsed.spatials.map((spatial) => spatial.symbol);
25 const res = await db.query(`select id, svg, width, height from symbol where id in (${symlist.map(s => convert.swu2id(s)).join(',')})`);
26 const symbols = res.reduce((obj, row) => {
27 obj[convert.id2swu(row.id)] = row
28 return obj;
29 }, {})
30
31 let styling = style.parse(parsed.style);
32
33 if (styling.detailsym) {
34 styling.detailsym.forEach(sym => {
35 parsed.spatials[sym.index - 1].detail = sym.detail;
36 })
37 }
38
39 let x1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[0]));
40 let y1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[1]));
41 let x2 = parsed.max[0];
42 let y2 = parsed.max[1];
43
44 let background = '';
45 if (styling.padding) {
46 x1 -= styling.padding;
47 y1 -= styling.padding;
48 x2 += styling.padding;
49 y2 += styling.padding;
50 }
51 if (styling.background) {
52 background = `\n <rect x="${x1}" y="${y1}" width="${x2 - x1}" height="${y2 - y1}" style="fill:${styling.background};" />`
53 }
54
55 let svg = ` <text font-size="0">${swuSign}</text>${background}`
56
57 const line = styling.detail && styling.detail[0];
58 const fill = styling.detail && styling.detail[1];
59
60 svg += '\n' + parsed.spatials.map(spatial => {
61 let svg = symbols[spatial.symbol] ? symbols[spatial.symbol].svg : '';
62
63 let symLine = line;
64 if (spatial.detail) {
65 symLine = spatial.detail[0];
66 } else if (styling.colorize) {
67 symLine = swu.colorize(spatial.symbol);
68 }
69 if (symLine) {
70 svg = svg.replace(/class="sym-line"/, `class="sym-line" fill="${symLine}"`);
71 }
72
73 let symFill = fill;
74 if (spatial.detail && spatial.detail[1]) {
75 symFill = spatial.detail[1];
76 }
77 if (symFill) {
78 svg = svg.replace(/class="sym-fill" fill="#ffffff"/, `class="sym-fill" fill="${symFill}"`);
79 }
80
81 return ` <svg x="${spatial.coord[0]}" y="${spatial.coord[1]}">${svg}</svg>`;
82
83 }).join('\n');
84
85 return svg;
86}
87
88/**
89 * Function that creates an SVG image from an SWU sign with an optional style string
90 * @function swu.signSvg
91 * @param {string} swuSign - an SWU sign with optional style string
92 * @returns {string} sign svg
93 * @example
94 * // using promise.then
95 * swu.signSvg('𝠃𝤟𝤩񋛩𝣵𝤐񀀒𝤇𝣤񋚥𝤐𝤆񀀚𝣮𝣭').then( svg => {
96 * console.log(svg)
97 * })
98 * @example
99 * // using async/await
100 * const svg = await swu.signSvg('𝠃𝤟𝤩񋛩𝣵𝤐񀀒𝤇𝣤񋚥𝤐𝤆񀀚𝣮𝣭')
101 */
102 const signSvg = async (swuSign) => {
103 let parsed = swu.parse.sign(swuSign);
104 const blank = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1" height="1"></svg>';
105 if (!parsed.spatials) return blank;
106
107 let styling = style.parse(parsed.style);
108
109 let x1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[0]));
110 let y1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[1]));
111 let x2 = parsed.max[0];
112 let y2 = parsed.max[1];
113
114 let classes = '';
115 if (styling.classes) {
116 classes = ` class="${styling.classes}"`
117 }
118 let id = '';
119 if (styling.id) {
120 id = ` id="${styling.id}"`
121 }
122
123 if (styling.padding) {
124 x1 -= styling.padding;
125 y1 -= styling.padding;
126 x2 += styling.padding;
127 y2 += styling.padding;
128 }
129
130 let sizing = '';
131 if (styling.zoom != 'x') {
132 sizing = ` width="${(x2 - x1) * (styling.zoom ? styling.zoom : 1)}" height="${(y2 - y1) * (styling.zoom ? styling.zoom : 1)}"`;
133 }
134
135 let svg = `<svg${classes}${id} version="1.1" xmlns="http://www.w3.org/2000/svg"${sizing} viewBox="${x1} ${y1} ${(x2 - x1)} ${(y2 - y1)}">
136`
137
138 const body = await signSvgBody(swuSign);
139
140 return svg + body + '\n</svg>';
141}
142
143if (require.main === module) {
144 signSvg(process.argv[2]).then( res => {
145 if (process.argv[3]) {
146 fs.writeFileSync(process.argv[3], res)
147 } else {
148 console.log(res);
149 }
150 })
151} else {
152 module.exports = { signSvgBody, signSvg }
153}