UNPKG

10.2 kBJavaScriptView Raw
1/**
2* Sutton SignWriting Core Module v1.2.0 (https://github.com/sutton-signwriting/core)
3* Author: Steve Slevinski (https://SteveSlevinski.me)
4* convert.mjs is released under the MIT License.
5*/
6
7/**
8 * Object of regular expressions for FSW strings
9 *
10 * { symbol, coord, sort, box, prefix, spatial, signbox, sign, sortable }
11 * @alias fsw.re
12 * @type {object}
13 */
14let re = {
15 'symbol': 'S[123][0-9a-f]{2}[0-5][0-9a-f]',
16 'coord': '[0-9]{3}x[0-9]{3}',
17 'sort': 'A',
18 'box': '[BLMR]'
19};
20re.prefix = `(?:${re.sort}(?:${re.symbol})+)`;
21re.spatial = `${re.symbol}${re.coord}`;
22re.signbox = `${re.box}${re.coord}(?:${re.spatial})*`;
23re.sign = `${re.prefix}?${re.signbox}`;
24re.sortable = `${re.prefix}${re.signbox}`;
25
26/**
27 * Object of regular expressions for SWU strings in UTF-16
28 *
29 * { symbol, coord, sort, box, prefix, spatial, signbox, sign, sortable }
30 * @alias swu.re
31 * @type {object}
32 */
33let re$1 = {
34 'symbol': '(?:(?:\uD8C0[\uDC01-\uDFFF])|(?:[\uD8C1-\uD8FC][\uDC00-\uDFFF])|(?:\uD8FD[\uDC00-\uDC80]))',
35 'coord': '(?:\uD836[\uDC0C-\uDDFF]){2}',
36 'sort': '\uD836\uDC00',
37 'box': '\uD836[\uDC01-\uDC04]'
38};
39re$1.prefix = `(?:${re$1.sort}(?:${re$1.symbol})+)`;
40re$1.spatial = `${re$1.symbol}${re$1.coord}`;
41re$1.signbox = `${re$1.box}${re$1.coord}(?:${re$1.spatial})*`;
42re$1.sign = `${re$1.prefix}?${re$1.signbox}`;
43re$1.sortable = `${re$1.prefix}${re$1.signbox}`;
44
45/** The convert module contains functions to convert between Formal SignWriitng in ASCII (FSW) and SignWriting in Unicode (SWU) characters, along with other types of data.
46 * [Characters set definitions](https://tools.ietf.org/id/draft-slevinski-formal-signwriting-07.html#rfc.section.2.2)
47 * @module convert
48 */
49/**
50 * Function to convert an SWU structural marker to FSW equivalent
51 * @function convert.swu2mark
52 * @param {string} swuMark - character for SWU structural marker
53 * @returns {string} FSW structural marker
54 * @example
55 * convert.swu2mark('𝠀')
56 *
57 * return 'A'
58 */
59
60const swu2mark = swuMark => {
61 return {
62 '𝠀': 'A',
63 '𝠁': 'B',
64 '𝠂': 'L',
65 '𝠃': 'M',
66 '𝠄': 'R'
67 }[swuMark];
68};
69/**
70 * Function to convert an FSW structural marker to SWU equivalent
71 * @function convert.mark2swu
72 * @param {string} fswMark - character for FSW structural marker
73 * @returns {string} SWU structural marker
74 * @example
75 * convert.mark2swu('A')
76 *
77 * return '𝠀'
78 */
79
80
81const mark2swu = fswMark => {
82 return {
83 'A': '𝠀',
84 'B': '𝠁',
85 'L': '𝠂',
86 'M': '𝠃',
87 'R': '𝠄'
88 }[fswMark];
89};
90/**
91 * Function to convert an SWU number character to an integer
92 * @function convert.swu2num
93 * @param {string} swuNum - SWU number character
94 * @returns {number} Integer value for number
95 * @example
96 * convert.swu2num('ðĪ†')
97 *
98 * return 500
99 */
100
101
102const swu2num = swuNum => parseInt(swuNum.codePointAt(0)) - 0x1D80C + 250;
103/**
104 * Function to convert a number to an SWU number character
105 * @function convert.num2swu
106 * @param {number} num - Integer value for number
107 * @returns {string} SWU number character
108 * @example
109 * convert.num2swu(500)
110 *
111 * return 'ðĪ†'
112 */
113
114
115const num2swu = num => String.fromCodePoint(0x1D80C + parseInt(num) - 250);
116/**
117 * Function to convert two SWU number characters to an array of x,y integers
118 * @function convert.swu2coord
119 * @param {string} swuCoord - Two SWU number character
120 * @returns {number[]} Array of x,y integers
121 * @example
122 * convert.swu2coord('ðĪ†ðĪ†')
123 *
124 * return [500, 500]
125 */
126
127
128const swu2coord = swuCoord => [swu2num(swuCoord.slice(0, 2)), swu2num(swuCoord.slice(2, 4))];
129/**
130 * Function to convert an array of x,y integers to two SWU number characters
131 * @function convert.coord2swu
132 * @param {number[]} coord - Array of x,y integers
133 * @returns {string} Two SWU number character
134 * @example
135 * convert.coord2swu([500, 500])
136 *
137 * return 'ðĪ†ðĪ†'
138 */
139
140
141const coord2swu = coord => coord.map(num => num2swu(num)).join('');
142/**
143 * Function to convert an FSW coordinate string to an array of x,y integers
144 * @function convert.fsw2coord
145 * @param {string} fswCoord - An FSW coordinate string
146 * @returns {number[]} Array of x,y integers
147 * @example
148 * convert.fsw2coord('500x500')
149 *
150 * return [500, 500]
151 */
152
153
154const fsw2coord = fswCoord => fswCoord.split('x').map(num => parseInt(num));
155/**
156 * Function to convert an array of x,y integers to an FSW coordinate string
157 * @function convert.coord2fsw
158 * @param {number[]} coord - Array of x,y integers
159 * @returns {string} An FSW coordinate string
160 * @example
161 * convert.coord2fsw([500, 500])
162 *
163 * return '500x500'
164 */
165
166
167const coord2fsw = coord => coord.join('x');
168/**
169 * Function to convert an SWU symbol character to a code point on plane 4
170 * @function convert.swu2code
171 * @param {string} swuSym - SWU symbol character
172 * @returns {number} Code point on plane 4
173 * @example
174 * convert.swu2code('ņ€€')
175 *
176 * return 0x40001
177 */
178
179
180const swu2code = swuSym => parseInt(swuSym.codePointAt(0));
181/**
182 * Function to convert a code point on plane 4 to an SWU symbol character
183 * @function convert.code2swu
184 * @param {number} code - Code point on plane 4
185 * @returns {string} SWU symbol character
186 * @example
187 * convert.code2swu(0x40001)
188 *
189 * return 'ņ€€'
190 */
191
192
193const code2swu = code => String.fromCodePoint(code);
194/**
195 * Function to convert an SWU symbol character to a 16-bit ID
196 * @function convert.swu2id
197 * @param {string} swuSym - SWU symbol character
198 * @returns {number} 16-bit ID
199 * @example
200 * convert.swu2id('ņ€€')
201 *
202 * return 1
203 */
204
205
206const swu2id = swuSym => swu2code(swuSym) - 0x40000;
207/**
208 * Function to convert a 16-bit ID to an SWU symbol character
209 * @function convert.id2swu
210 * @param {number} id - 16-bit ID
211 * @returns {string} SWU symbol character
212 * @example
213 * convert.id2swu(1)
214 *
215 * return 'ņ€€'
216 */
217
218
219const id2swu = id => code2swu(id + 0x40000);
220/**
221 * Function to convert an FSW symbol key to a 16-bit ID
222 * @function convert.key2id
223 * @param {string} key - FSW symbol key
224 * @returns {number} 16-bit ID
225 * @example
226 * convert.key2id('S10000')
227 *
228 * return 1
229 */
230
231
232const key2id = key => 1 + (parseInt(key.slice(1, 4), 16) - 256) * 96 + parseInt(key.slice(4, 5), 16) * 16 + parseInt(key.slice(5, 6), 16);
233/**
234 * Function to convert a 16-bit ID to an FSW symbol key
235 * @function convert.id2key
236 * @param {number} id - 16-bit ID
237 * @returns {string} FSW symbol key
238 * @example
239 * convert.id2key(1)
240 *
241 * return 'S10000'
242 */
243
244
245const id2key = id => {
246 const symcode = id - 1;
247 const base = parseInt(symcode / 96);
248 const fill = parseInt((symcode - base * 96) / 16);
249 const rotation = parseInt(symcode - base * 96 - fill * 16);
250 return 'S' + (base + 0x100).toString(16) + fill.toString(16) + rotation.toString(16);
251};
252/**
253 * Function to convert an SWU symbol character to an FSW symbol key
254 * @function convert.swu2key
255 * @param {string} swuSym - SWU symbol character
256 * @returns {string} FSW symbol key
257 * @example
258 * convert.swu2key('ņ€€')
259 *
260 * return 'S10000'
261 */
262
263
264const swu2key = swuSym => {
265 const symcode = swu2code(swuSym) - 0x40001;
266 const base = parseInt(symcode / 96);
267 const fill = parseInt((symcode - base * 96) / 16);
268 const rotation = parseInt(symcode - base * 96 - fill * 16);
269 return 'S' + (base + 0x100).toString(16) + fill.toString(16) + rotation.toString(16);
270};
271/**
272 * Function to convert an FSW symbol key to an SWU symbol character
273 * @function convert.key2swu
274 * @param {string} key - FSW symbol key
275 * @returns {string} SWU symbol character
276 * @example
277 * convert.key2swu('S10000')
278 *
279 * return 'ņ€€'
280 */
281
282
283const key2swu = key => code2swu(0x40001 + (parseInt(key.slice(1, 4), 16) - 256) * 96 + parseInt(key.slice(4, 5), 16) * 16 + parseInt(key.slice(5, 6), 16));
284/**
285 * Function to convert SWU text to FSW text
286 * @function convert.swu2fsw
287 * @param {string} swuText - SWU text
288 * @returns {string} FSW text
289 * @example
290 * convert.swu2fsw('𝠀ņ€€’ņ€€šņ‹šĨņ‹›Đ𝠃ðĪŸðĪĐņ‹›ĐðĢĩðĪņ€€’ðĪ‡ðĢĪņ‹šĨðĪðĪ†ņ€€šðĢŪðĢ­')
291 *
292 * return 'AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475'
293 */
294
295
296const swu2fsw = swuText => {
297 if (!swuText) return '';
298 let fsw = swuText.replace(/𝠀/g, "A").replace(/𝠁/g, "B").replace(/𝠂/g, "L").replace(/𝠃/g, "M").replace(/𝠄/g, "R");
299 const syms = fsw.match(new RegExp(re$1.symbol, 'g'));
300
301 if (syms) {
302 syms.forEach(function (sym) {
303 fsw = fsw.replace(sym, swu2key(sym));
304 });
305 }
306
307 const coords = fsw.match(new RegExp(re$1.coord, 'g'));
308
309 if (coords) {
310 coords.forEach(function (coord) {
311 fsw = fsw.replace(coord, swu2coord(coord).join('x'));
312 });
313 }
314
315 return fsw;
316};
317/**
318 * Function to convert FSW text to SWU text
319 * @function convert.fsw2swu
320 * @param {string} fswText - FSW text
321 * @returns {string} SWU text
322 * @example
323 * convert.fsw2swu('AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475')
324 *
325 * return '𝠀ņ€€’ņ€€šņ‹šĨņ‹›Đ𝠃ðĪŸðĪĐņ‹›ĐðĢĩðĪņ€€’ðĪ‡ðĢĪņ‹šĨðĪðĪ†ņ€€šðĢŪðĢ­'
326 */
327
328
329const fsw2swu = fswText => {
330 if (!fswText) return '';
331 const prefixes = fswText.match(new RegExp(re.prefix, 'g'));
332
333 if (prefixes) {
334 prefixes.forEach(function (prefix) {
335 fswText = fswText.replace(prefix, '𝠀' + prefix.slice(1).match(/.{6}/g).map(key => key2swu(key)).join(''));
336 });
337 }
338
339 const boxes = fswText.match(new RegExp(re.box + re.coord, 'g'));
340
341 if (boxes) {
342 boxes.forEach(function (boxes) {
343 fswText = fswText.replace(boxes, mark2swu(boxes.slice(0, 1)) + coord2swu(fsw2coord(boxes.slice(1, 8))));
344 });
345 }
346
347 const spatials = fswText.match(new RegExp(re.spatial, 'g'));
348
349 if (spatials) {
350 spatials.forEach(function (spatial) {
351 fswText = fswText.replace(spatial, key2swu(spatial.slice(0, 6)) + coord2swu(fsw2coord(spatial.slice(6, 13))));
352 });
353 }
354
355 return fswText;
356};
357
358export { code2swu, coord2fsw, coord2swu, fsw2coord, fsw2swu, id2key, id2swu, key2id, key2swu, mark2swu, num2swu, swu2code, swu2coord, swu2fsw, swu2id, swu2key, swu2mark, swu2num };
359
360/* support ongoing development on https://patreon.com/signwriting */