UNPKG

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