UNPKG

7.58 kBJavaScriptView Raw
1/**
2* Sutton SignWriting Core Module v1.1.0
3* https://github.com/Slevinski/SignWriting
4* Copyright (c) 2007-2019, Steve Slevinski
5* fsw.mjs is released under the MIT License.
6*/
7
8/**
9 * Object of regular expressions for FSW strings
10 *
11 * { symbol, coord, sort, box, prefix, spatial, signbox, sign, term }
12 * @alias fsw.re
13 * @type {object}
14 */
15let re = {
16 'symbol': 'S[123][0-9a-f]{2}[0-5][0-9a-f]',
17 'coord': '[0-9]{3}x[0-9]{3}',
18 'sort': 'A',
19 'box': '[BLMR]'
20};
21re.prefix = `(?:${re.sort}(?:${re.symbol})+)`;
22re.spatial = `${re.symbol}${re.coord}`;
23re.signbox = `${re.box}${re.coord}(?:${re.spatial})*`;
24re.sign = `${re.prefix}?${re.signbox}`;
25re.term = `${re.prefix}${re.signbox}`;
26
27/**
28 * Object of regular expressions for style strings
29 *
30 * { colorize, colorhex, colorname, padding, zoom, zoomsym, classbase, id, colorbase, color, colors, background, detail, detailsym, classes, full }
31 * @alias style.re
32 * @type {object}
33 */
34let re$1 = {
35 'colorize': 'C',
36 'colorhex': '(?:[0-9a-fA-F]{3}){1,2}',
37 'colorname': '[a-zA-Z]+',
38 'padding': 'P[0-9]{2}',
39 'zoom': 'Z(?:[0-9]+(?:\\.[0-9]+)?|x)',
40 'zoomsym': 'Z[0-9]{2},[0-9]+(?:\\.[0-9]+)?(?:,[0-9]{3}x[0-9]{3})?',
41 'classbase': '-?[_a-zA-Z][_a-zA-Z0-9-]{0,100}',
42 'id': '[a-zA-Z][_a-zA-Z0-9-]{0,100}'
43};
44re$1.colorbase = `(?:${re$1.colorhex}|${re$1.colorname})`;
45re$1.color = `_${re$1.colorbase}_`;
46re$1.colors = `_${re$1.colorbase}(?:,${re$1.colorbase})?_`;
47re$1.background = `G${re$1.color}`;
48re$1.detail = `D${re$1.colors}`;
49re$1.detailsym = `D[0-9]{2}${re$1.colors}`;
50re$1.classes = `${re$1.classbase}(?: ${re$1.classbase})*`;
51re$1.full = `-(${re$1.colorize})?(${re$1.padding})?(${re$1.background})?(${re$1.detail})?(${re$1.zoom})?(?:-((?:${re$1.detailsym})*)((?:${re$1.zoomsym})*))?(?:-(${re$1.classes})?!(?:(${re$1.id})!)?)?`;
52
53/** 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.
54 * [Characters set definitions](https://tools.ietf.org/id/draft-slevinski-formal-signwriting-07.html#rfc.section.2.2)
55 * @module convert
56 */
57/**
58 * Function to convert an FSW coordinate string to an array of x,y integers
59 * @function convert.fsw2coord
60 * @param {string} fswCoord - An FSW coordinate string
61 * @returns {number[]} Array of x,y integers
62 * @example
63 * convert.fsw2coord('500x500')
64 *
65 * return [500, 500]
66 */
67
68
69const fsw2coord = fswCoord => fswCoord.split('x').map(num => parseInt(num));
70
71const parse = {
72 /**
73 * Function to parse an fsw symbol with optional coordinate and style string
74 * @function fsw.parse.symbol
75 * @param {string} fswSym - an fsw symbol
76 * @returns {object} elements of fsw symbol
77 * @example
78 * fsw.parse.symbol('S10000500x500-C')
79 *
80 * return {
81 * 'symbol': 'S10000',
82 * 'coord': [500, 500],
83 * 'style': '-C'
84 * }
85 */
86 symbol: fswSym => {
87 const regex = `^(${re.symbol})(${re.coord})?(${re$1.full})?`;
88 const symbol = typeof fswSym === 'string' ? fswSym.match(new RegExp(regex)) : undefined;
89 return {
90 'symbol': symbol ? symbol[1] : undefined,
91 'coord': symbol && symbol[2] ? fsw2coord(symbol[2]) : undefined,
92 'style': symbol ? symbol[3] : undefined
93 };
94 },
95
96 /**
97 * Function to parse an fsw sign with style string
98 * @function fsw.parse.sign
99 * @param {string} fswSign - an fsw sign
100 * @returns {object} elements of fsw sign
101 * @example
102 * fsw.parse.sign('AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475-C')
103 *
104 * return {
105 * sequence: ['S10011', 'S10019', 'S2e704', 'S2e748'],
106 * box: 'M',
107 * max: [525, 535],
108 * spatials: [
109 * {
110 * symbol: 'S2e748',
111 * coord: [483, 510]
112 * },
113 * {
114 * symbol: 'S10011',
115 * coord: [501, 466]
116 * },
117 * {
118 * symbol: 'S2e704',
119 * coord: [510, 500]
120 * },
121 * {
122 * symbol: 'S10019',
123 * coord: [476, 475]
124 * }
125 * ],
126 * style: '-C'
127 * }
128 */
129 sign: fswSign => {
130 const regex = `^(${re.prefix})?(${re.signbox})(${re$1.full})?`;
131 const sign = typeof fswSign === 'string' ? fswSign.match(new RegExp(regex)) : undefined;
132
133 if (sign) {
134 return {
135 'sequence': sign[1] ? sign[1].slice(1).match(/.{6}/g) : undefined,
136 'box': sign[2][0],
137 'max': fsw2coord(sign[2].slice(1, 8)),
138 'spatials': sign[2].length < 9 ? undefined : sign[2].slice(8).match(/(.{13})/g).map(m => {
139 return {
140 symbol: m.slice(0, 6),
141 coord: [parseInt(m.slice(6, 9)), parseInt(m.slice(10, 13))]
142 };
143 }),
144 'style': sign[3]
145 };
146 } else {
147 return {};
148 }
149 }
150};
151
152/**
153 * Array of numbers for kinds of symbols: writing, location, and punctuation.
154 * @alias fsw.kind
155 * @type {array}
156 */
157
158const kind = [0x100, 0x37f, 0x387];
159/**
160 * Array of numbers for categories of symbols: hand, movement, dynamics, head, trunk & limb, location, and punctuation.
161 * @alias fsw.category
162 * @type {array}
163 */
164
165const category = [0x100, 0x205, 0x2f7, 0x2ff, 0x36d, 0x37f, 0x387];
166/**
167 * Array of numbers for the 30 symbol groups.
168 * @alias fsw.group
169 * @type {array}
170 */
171
172const group = [0x100, 0x10e, 0x11e, 0x144, 0x14c, 0x186, 0x1a4, 0x1ba, 0x1cd, 0x1f5, 0x205, 0x216, 0x22a, 0x255, 0x265, 0x288, 0x2a6, 0x2b7, 0x2d5, 0x2e3, 0x2f7, 0x2ff, 0x30a, 0x32a, 0x33b, 0x359, 0x36d, 0x376, 0x37f, 0x387];
173/**
174 * Object of symbol ranges with starting and ending numbers.
175 *
176 * { all, writing, hand, movement, dynamic, head, hcenter, vcenter, trunk, limb, location, punctuation }
177 * @alias fsw.ranges
178 * @type {object}
179 */
180
181const ranges = {
182 'all': [0x100, 0x38b],
183 'writing': [0x100, 0x37e],
184 'hand': [0x100, 0x204],
185 'movement': [0x205, 0x2f6],
186 'dynamic': [0x2f7, 0x2fe],
187 'head': [0x2ff, 0x36c],
188 'hcenter': [0x2ff, 0x36c],
189 'vcenter': [0x2ff, 0x375],
190 'trunk': [0x36d, 0x375],
191 'limb': [0x376, 0x37e],
192 'location': [0x37f, 0x386],
193 'punctuation': [0x387, 0x38b]
194};
195/**
196 * Function to test if symbol is of a certain type.
197 * @function fsw.isType
198 * @param {string} key - an FSW symbol key
199 * @param {string} type - the name of a symbol range
200 * @returns {boolean} is symbol of specified type
201 * @example
202 * fsw.isType('S10000', 'hand')
203 *
204 * return true
205 */
206
207const isType = (key, type) => {
208 const parsed = parse.symbol(key);
209
210 if (parsed.symbol) {
211 const dec = parseInt(parsed.symbol.slice(1, 4), 16);
212 const range = ranges[type];
213
214 if (range) {
215 return range[0] <= dec && range[1] >= dec;
216 }
217 }
218
219 return false;
220};
221
222/**
223 * Array of colors associated with the seven symbol categories.
224 * @alias fsw.colors
225 * @type {array}
226 */
227
228const colors = ['#0000CC', '#CC0000', '#FF0099', '#006600', '#000000', '#884411', '#FF9900'];
229/**
230 * Function that returns the standardized color for a symbol.
231 * @function fsw.colorize
232 * @param {string} key - an FSW symbol key
233 * @returns {string} name of standardized color for symbol
234 * @example
235 * fsw.colorize('S10000')
236 *
237 * return '#0000CC'
238 */
239
240const colorize = key => {
241 const parsed = parse.symbol(key);
242 let color = '#000000';
243
244 if (parsed.symbol) {
245 const dec = parseInt(parsed.symbol.slice(1, 4), 16);
246 const index = category.findIndex(val => val > dec);
247 color = colors[index < 0 ? 6 : index - 1];
248 }
249
250 return color;
251};
252
253export { category, colorize, colors, group, isType, kind, parse, ranges, re };
254
255/* help fund development on https://patreon.com/signwriting */