1 | /*!
|
2 | * The Sutton SignWriting Web Components
|
3 | */
|
4 | import { c as createCommonjsModule, a as commonjsGlobal } from './_commonjsHelpers-383fba37.js';
|
5 |
|
6 | var fsw = createCommonjsModule(function (module, exports) {
|
7 | /**
|
8 | * Sutton SignWriting Core Module v1.5.4 (https://github.com/sutton-signwriting/core)
|
9 | * Author: Steve Slevinski (https://SteveSlevinski.me)
|
10 | * fsw.js is released under the MIT License.
|
11 | */
|
12 |
|
13 | (function (global, factory) {
|
14 | factory(exports) ;
|
15 | })(commonjsGlobal, (function (exports) {
|
16 | /**
|
17 | * Object of regular expressions for FSW strings
|
18 | *
|
19 | * @alias fsw.re
|
20 | * @property {string} symbol - regular expressions for a symbol
|
21 | * @property {string} coord - regular expressions for a coordinate
|
22 | * @property {string} sort - regular expressions for the sorting marker
|
23 | * @property {string} box - regular expression for a signbox marker
|
24 | * @property {string} prefix - regular expression for a sorting marker followed by one or more symbols
|
25 | * @property {string} spatial - regular expression for a symbol followed by a coordinate
|
26 | * @property {string} signbox - regular expression for a signbox marker, max coordinate and zero or more spatial symbols
|
27 | * @property {string} sign - regular expression for an optional prefix followed by a signbox
|
28 | * @property {string} sortable - regular expression for a mandatory prefix followed by a signbox
|
29 | */
|
30 | let re$1 = {
|
31 | 'symbol': 'S[123][0-9a-f]{2}[0-5][0-9a-f]',
|
32 | 'coord': '[0-9]{3}x[0-9]{3}',
|
33 | 'sort': 'A',
|
34 | 'box': '[BLMR]'
|
35 | };
|
36 | re$1.prefix = `(?:${re$1.sort}(?:${re$1.symbol})+)`;
|
37 | re$1.spatial = `${re$1.symbol}${re$1.coord}`;
|
38 | re$1.signbox = `${re$1.box}${re$1.coord}(?:${re$1.spatial})*`;
|
39 | re$1.sign = `${re$1.prefix}?${re$1.signbox}`;
|
40 | re$1.sortable = `${re$1.prefix}${re$1.signbox}`;
|
41 |
|
42 | /**
|
43 | * Object of regular expressions for style strings
|
44 | *
|
45 | * @alias style.re
|
46 | * @type {object}
|
47 | * @property {string} colorize - regular expression for colorize section
|
48 | * @property {string} colorhex - regular expression for color hex values with 3 or 6 characters
|
49 | * @property {string} colorname - regular expression for css color name
|
50 | * @property {string} padding - regular expression for padding section
|
51 | * @property {string} zoom - regular expression for zoom section
|
52 | * @property {string} classbase - regular expression for class name definition
|
53 | * @property {string} id - regular expression for id definition
|
54 | * @property {string} colorbase - regular expression for color hex or color name
|
55 | * @property {string} color - regular expression for single color entry
|
56 | * @property {string} colors - regular expression for double color entry
|
57 | * @property {string} background - regular expression for background section
|
58 | * @property {string} detail - regular expression for color details for line and optional fill
|
59 | * @property {string} detailsym - regular expression for color details for individual symbols
|
60 | * @property {string} classes - regular expression for one or more class names
|
61 | * @property {string} full - full regular expression for style string
|
62 | */
|
63 | let re = {
|
64 | 'colorize': 'C',
|
65 | 'colorhex': '(?:[0-9a-fA-F]{3}){1,2}',
|
66 | 'colorname': '[a-zA-Z]+',
|
67 | 'padding': 'P[0-9]{2}',
|
68 | 'zoom': 'Z(?:[0-9]+(?:\\.[0-9]+)?|x)',
|
69 | 'classbase': '-?[_a-zA-Z][_a-zA-Z0-9-]{0,100}',
|
70 | 'id': '[a-zA-Z][_a-zA-Z0-9-]{0,100}'
|
71 | };
|
72 | re.colorbase = `(?:${re.colorhex}|${re.colorname})`;
|
73 | re.color = `_${re.colorbase}_`;
|
74 | re.colors = `_${re.colorbase}(?:,${re.colorbase})?_`;
|
75 | re.background = `G${re.color}`;
|
76 | re.detail = `D${re.colors}`;
|
77 | re.detailsym = `D[0-9]{2}${re.colors}`;
|
78 | re.classes = `${re.classbase}(?: ${re.classbase})*`;
|
79 | re.full = `-(${re.colorize})?(${re.padding})?(${re.background})?(${re.detail})?(${re.zoom})?(?:-((?:${re.detailsym})*))?(?:-(${re.classes})?!(?:(${re.id})!)?)?`;
|
80 |
|
81 | const prefixColor = color => {
|
82 | const regex = new RegExp(`^${re.colorhex}$`);
|
83 | return (regex.test(color) ? '#' : '') + color;
|
84 | };
|
85 |
|
86 | const definedProps = obj => Object.fromEntries(Object.entries(obj).filter(([k, v]) => v !== undefined));
|
87 | /**
|
88 | * Function to parse style string to object
|
89 | * @function style.parse
|
90 | * @param {string} styleString - a style string
|
91 | * @returns {StyleObject} elements of style string
|
92 | * @example
|
93 | * style.parse('-CP10G_blue_D_red,Cyan_')
|
94 | *
|
95 | * return {
|
96 | * 'colorize': true,
|
97 | * 'padding': 10,
|
98 | * 'background': 'blue',
|
99 | * 'detail': ['red', 'Cyan']
|
100 | * }
|
101 | */
|
102 |
|
103 |
|
104 | const parse$1 = styleString => {
|
105 | const regex = `^${re.full}`;
|
106 | const m = (typeof styleString === 'string' ? styleString.match(new RegExp(regex)) : []) || [];
|
107 | return definedProps({
|
108 | 'colorize': !m[1] ? undefined : !!m[1],
|
109 | 'padding': !m[2] ? undefined : parseInt(m[2].slice(1)),
|
110 | 'background': !m[3] ? undefined : prefixColor(m[3].slice(2, -1)),
|
111 | 'detail': !m[4] ? undefined : m[4].slice(2, -1).split(',').map(prefixColor),
|
112 | 'zoom': !m[5] ? undefined : m[5] === 'Zx' ? 'x' : parseFloat(m[5].slice(1)),
|
113 | 'detailsym': !m[6] ? undefined : m[6].match(new RegExp(re.detailsym, 'g')).map(val => {
|
114 | const parts = val.split('_');
|
115 | const detail = parts[1].split(',').map(prefixColor);
|
116 | return {
|
117 | 'index': parseInt(parts[0].slice(1)),
|
118 | 'detail': detail
|
119 | };
|
120 | }),
|
121 | 'classes': !m[7] ? undefined : m[7],
|
122 | 'id': !m[8] ? undefined : m[8]
|
123 | });
|
124 | };
|
125 |
|
126 | /** 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.
|
127 | * [Characters set definitions](https://tools.ietf.org/id/draft-slevinski-formal-signwriting-09.html#name-characters)
|
128 | * @module convert
|
129 | */
|
130 | /**
|
131 | * Function to convert an FSW coordinate string to an array of x,y integers
|
132 | * @function convert.fsw2coord
|
133 | * @param {string} fswCoord - An FSW coordinate string
|
134 | * @returns {number[]} Array of x,y integers
|
135 | * @example
|
136 | * convert.fsw2coord('500x500')
|
137 | *
|
138 | * return [500, 500]
|
139 | */
|
140 |
|
141 |
|
142 | const fsw2coord = fswCoord => fswCoord.split('x').map(num => parseInt(num));
|
143 |
|
144 | const parse = {
|
145 | /**
|
146 | * Function to parse an fsw symbol with optional coordinate and style string
|
147 | * @function fsw.parse.symbol
|
148 | * @param {string} fswSym - an fsw symbol
|
149 | * @returns {SymbolObject} elements of fsw symbol
|
150 | * @example
|
151 | * fsw.parse.symbol('S10000500x500-C')
|
152 | *
|
153 | * return {
|
154 | * 'symbol': 'S10000',
|
155 | * 'coord': [500, 500],
|
156 | * 'style': '-C'
|
157 | * }
|
158 | */
|
159 | symbol: fswSym => {
|
160 | const regex = `^(${re$1.symbol})(${re$1.coord})?(${re.full})?`;
|
161 | const symbol = typeof fswSym === 'string' ? fswSym.match(new RegExp(regex)) : undefined;
|
162 | return {
|
163 | 'symbol': symbol ? symbol[1] : undefined,
|
164 | 'coord': symbol && symbol[2] ? fsw2coord(symbol[2]) : undefined,
|
165 | 'style': symbol ? symbol[3] : undefined
|
166 | };
|
167 | },
|
168 |
|
169 | /**
|
170 | * Function to parse an fsw sign with style string
|
171 | * @function fsw.parse.sign
|
172 | * @param {string} fswSign - an fsw sign
|
173 | * @returns { SignObject } elements of fsw sign
|
174 | * @example
|
175 | * fsw.parse.sign('AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475-C')
|
176 | *
|
177 | * return {
|
178 | * sequence: ['S10011', 'S10019', 'S2e704', 'S2e748'],
|
179 | * box: 'M',
|
180 | * max: [525, 535],
|
181 | * spatials: [
|
182 | * {
|
183 | * symbol: 'S2e748',
|
184 | * coord: [483, 510]
|
185 | * },
|
186 | * {
|
187 | * symbol: 'S10011',
|
188 | * coord: [501, 466]
|
189 | * },
|
190 | * {
|
191 | * symbol: 'S2e704',
|
192 | * coord: [510, 500]
|
193 | * },
|
194 | * {
|
195 | * symbol: 'S10019',
|
196 | * coord: [476, 475]
|
197 | * }
|
198 | * ],
|
199 | * style: '-C'
|
200 | * }
|
201 | */
|
202 | sign: fswSign => {
|
203 | const regex = `^(${re$1.prefix})?(${re$1.signbox})(${re.full})?`;
|
204 | const sign = typeof fswSign === 'string' ? fswSign.match(new RegExp(regex)) : undefined;
|
205 |
|
206 | if (sign) {
|
207 | return {
|
208 | 'sequence': sign[1] ? sign[1].slice(1).match(/.{6}/g) : undefined,
|
209 | 'box': sign[2][0],
|
210 | 'max': fsw2coord(sign[2].slice(1, 8)),
|
211 | 'spatials': sign[2].length < 9 ? undefined : sign[2].slice(8).match(/(.{13})/g).map(m => {
|
212 | return {
|
213 | symbol: m.slice(0, 6),
|
214 | coord: [parseInt(m.slice(6, 9)), parseInt(m.slice(10, 13))]
|
215 | };
|
216 | }),
|
217 | 'style': sign[3]
|
218 | };
|
219 | } else {
|
220 | return {};
|
221 | }
|
222 | },
|
223 |
|
224 | /**
|
225 | * Function to parse an fsw text
|
226 | * @function fsw.parse.text
|
227 | * @param {string} fswText - an fsw text
|
228 | * @returns {string[]} fsw signs and punctuations
|
229 | * @example
|
230 | * fsw.parse.text('AS14c20S27106M518x529S14c20481x471S27106503x489 AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468 S38800464x496')
|
231 | *
|
232 | * return [
|
233 | * 'AS14c20S27106M518x529S14c20481x471S27106503x489',
|
234 | * 'AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468',
|
235 | * 'S38800464x496'
|
236 | * ]
|
237 | */
|
238 | text: fswText => {
|
239 | if (typeof fswText !== 'string') return [];
|
240 | const regex = `(${re$1.sign}(${re.full})?|${re$1.spatial}(${re.full})?)`;
|
241 | const matches = fswText.match(new RegExp(regex, 'g'));
|
242 | return matches ? [...matches] : [];
|
243 | }
|
244 | };
|
245 |
|
246 | const compose = {
|
247 | /**
|
248 | * Function to compose an fsw symbol with optional coordinate and style string
|
249 | * @function fsw.compose.symbol
|
250 | * @param {SymbolObject} fswSymObject - an fsw symbol object
|
251 | * @returns {string} an fsw symbol string
|
252 | * @example
|
253 | * fsw.compose.symbol({
|
254 | * 'symbol': 'S10000',
|
255 | * 'coord': [480, 480],
|
256 | * 'style': '-C'
|
257 | * })
|
258 | *
|
259 | * return 'S10000480x480-C'
|
260 | */
|
261 | symbol: fswSymObject => {
|
262 | if (typeof fswSymObject.symbol === 'string') {
|
263 | const symbol = (fswSymObject.symbol.match(re$1.symbol) || [''])[0];
|
264 |
|
265 | if (symbol) {
|
266 | const x = (fswSymObject.coord && fswSymObject.coord[0] || '').toString();
|
267 | const y = (fswSymObject.coord && fswSymObject.coord[1] || '').toString();
|
268 | const coord = ((x + 'x' + y).match(re$1.coord) || [''])[0] || '';
|
269 | const styleStr = typeof fswSymObject.style === 'string' && (fswSymObject.style.match(re.full) || [''])[0] || '';
|
270 | return symbol + coord + styleStr;
|
271 | }
|
272 | }
|
273 |
|
274 | return undefined;
|
275 | },
|
276 |
|
277 | /**
|
278 | * Function to compose an fsw sign with style string
|
279 | * @function fsw.compose.sign
|
280 | * @param {SignObject} fswSignObject - an fsw symbol object
|
281 | * @returns {string} an fsw sign string
|
282 | * @example
|
283 | * fsw.compose.sign({
|
284 | * sequence: ['S10011', 'S10019', 'S2e704', 'S2e748'],
|
285 | * box: 'M',
|
286 | * max: [525, 535],
|
287 | * spatials: [
|
288 | * {
|
289 | * symbol: 'S2e748',
|
290 | * coord: [483, 510]
|
291 | * },
|
292 | * {
|
293 | * symbol: 'S10011',
|
294 | * coord: [501, 466]
|
295 | * },
|
296 | * {
|
297 | * symbol: 'S2e704',
|
298 | * coord: [510, 500]
|
299 | * },
|
300 | * {
|
301 | * symbol: 'S10019',
|
302 | * coord: [476, 475]
|
303 | * }
|
304 | * ],
|
305 | * style: '-C'
|
306 | * })
|
307 | *
|
308 | * return 'AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475-C'
|
309 | */
|
310 | sign: fswSignObject => {
|
311 | let box = typeof fswSignObject.box !== 'string' ? 'M' : (fswSignObject.box + 'M').match(re$1.box);
|
312 | const x = (fswSignObject.max && fswSignObject.max[0] || '').toString();
|
313 | const y = (fswSignObject.max && fswSignObject.max[1] || '').toString();
|
314 | const max = ((x + 'x' + y).match(re$1.coord) || [''])[0] || '';
|
315 | if (!max) return undefined;
|
316 | let prefix = '';
|
317 |
|
318 | if (fswSignObject.sequence && Array.isArray(fswSignObject.sequence)) {
|
319 | prefix = fswSignObject.sequence.map(key => (key.match(re$1.symbol) || [''])[0]).join('');
|
320 | prefix = prefix ? 'A' + prefix : '';
|
321 | }
|
322 |
|
323 | let signbox = '';
|
324 |
|
325 | if (fswSignObject.spatials && Array.isArray(fswSignObject.spatials)) {
|
326 | signbox = fswSignObject.spatials.map(spatial => {
|
327 | if (typeof spatial.symbol === 'string') {
|
328 | const symbol = (spatial.symbol.match(re$1.symbol) || [''])[0];
|
329 |
|
330 | if (symbol) {
|
331 | const x = (spatial.coord && spatial.coord[0] || '').toString();
|
332 | const y = (spatial.coord && spatial.coord[1] || '').toString();
|
333 | const coord = ((x + 'x' + y).match(re$1.coord) || [''])[0] || '';
|
334 |
|
335 | if (coord) {
|
336 | return symbol + coord;
|
337 | }
|
338 | }
|
339 | }
|
340 |
|
341 | return '';
|
342 | }).join('');
|
343 | }
|
344 |
|
345 | const styleStr = typeof fswSignObject.style === 'string' && (fswSignObject.style.match(re.full) || [''])[0] || '';
|
346 | return prefix + box + max + signbox + styleStr;
|
347 | }
|
348 | };
|
349 |
|
350 | /**
|
351 | * Function to gather sizing information about an fsw sign or symbol
|
352 | * @function fsw.info
|
353 | * @param {string} fsw - an fsw sign or symbol
|
354 | * @returns {SegmentInfo} information about the fsw string
|
355 | * @example
|
356 | * fsw.info('AS14c20S27106L518x529S14c20481x471S27106503x489-P10Z2')
|
357 | *
|
358 | * return {
|
359 | * minX: 481,
|
360 | * minY: 471,
|
361 | * width: 37,
|
362 | * height: 58,
|
363 | * lane: -1,
|
364 | * padding: 10,
|
365 | * segment: 'sign',
|
366 | * zoom: 2
|
367 | * }
|
368 | */
|
369 |
|
370 | const info = fsw => {
|
371 | let lanes = {
|
372 | "B": 0,
|
373 | "L": -1,
|
374 | "M": 0,
|
375 | "R": 1
|
376 | };
|
377 | let parsed = parse.sign(fsw);
|
378 | let width, height, segment, x1, x2, y1, y2, lane;
|
379 |
|
380 | if (parsed.spatials) {
|
381 | x1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[0]));
|
382 | x2 = parsed.max[0];
|
383 | width = x2 - x1;
|
384 | y1 = Math.min(...parsed.spatials.map(spatial => spatial.coord[1]));
|
385 | y2 = parsed.max[1];
|
386 | height = y2 - y1;
|
387 | segment = 'sign';
|
388 | lane = parsed.box;
|
389 | } else {
|
390 | parsed = parse.symbol(fsw);
|
391 | lane = "M";
|
392 |
|
393 | if (parsed.coord) {
|
394 | x1 = parsed.coord[0];
|
395 | width = (500 - x1) * 2;
|
396 | y1 = parsed.coord[1];
|
397 | height = (500 - y1) * 2;
|
398 | segment = 'symbol';
|
399 | } else {
|
400 | x1 = 490;
|
401 | width = 20;
|
402 | y1 = 490;
|
403 | height = 20;
|
404 | segment = 'none';
|
405 | }
|
406 | }
|
407 |
|
408 | let style = parse$1(parsed.style);
|
409 | let zoom = style.zoom || 1;
|
410 | let padding = style.padding || 0;
|
411 | return {
|
412 | minX: x1,
|
413 | minY: y1,
|
414 | width: width,
|
415 | height: height,
|
416 | segment: segment,
|
417 | lane: lanes[lane],
|
418 | padding: padding,
|
419 | zoom: zoom
|
420 | };
|
421 | };
|
422 |
|
423 | const columnDefaults = {
|
424 | 'height': 500,
|
425 | 'width': 150,
|
426 | 'offset': 50,
|
427 | 'pad': 20,
|
428 | 'margin': 5,
|
429 | 'dynamic': false,
|
430 | 'background': undefined,
|
431 | 'punctuation': {
|
432 | 'spacing': true,
|
433 | 'pad': 30,
|
434 | 'pull': true
|
435 | },
|
436 | 'style': {
|
437 | 'detail': ['black', 'white'],
|
438 | 'zoom': 1
|
439 | }
|
440 | };
|
441 | /**
|
442 | * Function to an object of column options with default values
|
443 | *
|
444 | * @function fsw.columnDefaultsMerge
|
445 | * @param {ColumnOptions} options - object of column options
|
446 | * @returns {ColumnOptions} object of column options merged with column defaults
|
447 | * @example
|
448 | * fsw.columnDefaultsMerge({height: 500,width:150})
|
449 | *
|
450 | * return {
|
451 | * "height": 500,
|
452 | * "width": 150,
|
453 | * "offset": 50,
|
454 | * "pad": 20,
|
455 | * "margin": 5,
|
456 | * "dynamic": false,
|
457 | * "punctuation": {
|
458 | * "spacing": true,
|
459 | * "pad": 30,
|
460 | * "pull": true
|
461 | * },
|
462 | * "style": {
|
463 | * "detail": [
|
464 | * "black",
|
465 | * "white"
|
466 | * ],
|
467 | * "zoom": 1
|
468 | * }
|
469 | * }
|
470 | */
|
471 |
|
472 | const columnDefaultsMerge = options => {
|
473 | if (typeof options !== 'object') options = {};
|
474 | return { ...columnDefaults,
|
475 | ...options,
|
476 | punctuation: { ...columnDefaults.punctuation,
|
477 | ...options.punctuation
|
478 | },
|
479 | style: { ...columnDefaults.style,
|
480 | ...options.style
|
481 | }
|
482 | };
|
483 | };
|
484 | /**
|
485 | * Function to transform an FSW text to an array of columns
|
486 | *
|
487 | * @function fsw.columns
|
488 | * @param {string} fswText - FSW text of signs and punctuation
|
489 | * @param {ColumnOptions} options - object of column options
|
490 | * @returns {{options:ColumnOptions,widths:number[],columns:ColumnData}} object of column options, widths array, and column data
|
491 | * @example
|
492 | * fsw.columns('AS14c20S27106M518x529S14c20481x471S27106503x489 AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468 S38800464x496', {height: 500,width:150})
|
493 | *
|
494 | * return {
|
495 | * "options": {
|
496 | * "height": 500,
|
497 | * "width": 150,
|
498 | * "offset": 50,
|
499 | * "pad": 20,
|
500 | * "margin": 5,
|
501 | * "dynamic": false,
|
502 | * "punctuation": {
|
503 | * "spacing": true,
|
504 | * "pad": 30,
|
505 | * "pull": true
|
506 | * },
|
507 | * "style": {
|
508 | * "detail": [
|
509 | * "black",
|
510 | * "white"
|
511 | * ],
|
512 | * "zoom": 1
|
513 | * }
|
514 | * },
|
515 | * "widths": [
|
516 | * 150
|
517 | * ],
|
518 | * "columns": [
|
519 | * [
|
520 | * {
|
521 | * "x": 56,
|
522 | * "y": 20,
|
523 | * "minX": 481,
|
524 | * "minY": 471,
|
525 | * "width": 37,
|
526 | * "height": 58,
|
527 | * "lane": 0,
|
528 | * "padding": 0,
|
529 | * "segment": "sign",
|
530 | * "text": "AS14c20S27106M518x529S14c20481x471S27106503x489",
|
531 | * "zoom": 1
|
532 | * },
|
533 | * {
|
534 | * "x": 57,
|
535 | * "y": 118,
|
536 | * "minX": 482,
|
537 | * "minY": 468,
|
538 | * "width": 36,
|
539 | * "height": 65,
|
540 | * "lane": 0,
|
541 | * "padding": 0,
|
542 | * "segment": "sign",
|
543 | * "text": "AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468",
|
544 | * "zoom": 1
|
545 | * },
|
546 | * {
|
547 | * "x": 39,
|
548 | * "y": 203,
|
549 | * "minX": 464,
|
550 | * "minY": 496,
|
551 | * "width": 72,
|
552 | * "height": 8,
|
553 | * "lane": 0,
|
554 | * "padding": 0,
|
555 | * "segment": "symbol",
|
556 | * "text": "S38800464x496",
|
557 | * "zoom": 1
|
558 | * }
|
559 | * ]
|
560 | * ]
|
561 | * }
|
562 | */
|
563 |
|
564 |
|
565 | const columns = (fswText, options) => {
|
566 | if (typeof fswText !== 'string') return {};
|
567 | const values = columnDefaultsMerge(options);
|
568 | let input = parse.text(fswText);
|
569 | let cursor = 0;
|
570 | let cols = [];
|
571 | let col = [];
|
572 | let plus = 0;
|
573 | let center = parseInt(values.width / 2);
|
574 | let maxHeight = values.height - values.margin;
|
575 | let pullable = true;
|
576 | let finalize = false;
|
577 |
|
578 | for (let val of input) {
|
579 | let informed = info(val);
|
580 | cursor += plus;
|
581 |
|
582 | if (values.punctuation.spacing) {
|
583 | cursor += informed.segment == 'sign' ? values.pad : 0;
|
584 | } else {
|
585 | cursor += values.pad;
|
586 | }
|
587 |
|
588 | finalize = cursor + informed.height > maxHeight;
|
589 |
|
590 | if (finalize && informed.segment == 'symbol' && values.punctuation.pull && pullable) {
|
591 | finalize = false;
|
592 | pullable = false;
|
593 | }
|
594 |
|
595 | if (col.length == 0) {
|
596 | finalize = false;
|
597 | }
|
598 |
|
599 | if (finalize) {
|
600 | cursor = values.pad;
|
601 | cols.push(col);
|
602 | col = [];
|
603 | pullable = true;
|
604 | }
|
605 |
|
606 | col.push(Object.assign(informed, {
|
607 | x: center + values.offset * informed.lane - (500 - informed.minX) * informed.zoom * values.style.zoom,
|
608 | y: cursor,
|
609 | text: val
|
610 | }));
|
611 | cursor += informed.height * informed.zoom * values.style.zoom;
|
612 |
|
613 | if (values.punctuation.spacing) {
|
614 | plus = informed.segment == 'sign' ? values.pad : values.punctuation.pad;
|
615 | } else {
|
616 | plus = values.pad;
|
617 | }
|
618 | }
|
619 |
|
620 | if (col.length) {
|
621 | cols.push(col);
|
622 | } // over height issue when pulling punctuation
|
623 |
|
624 |
|
625 | if (values.punctuation.pull) {
|
626 | for (let col of cols) {
|
627 | let last = col[col.length - 1];
|
628 | let diff = last.y + last.height - (values.height - values.margin);
|
629 |
|
630 | if (diff > 0) {
|
631 | let adj = parseInt(diff / col.length) + 1;
|
632 |
|
633 | for (let i in col) {
|
634 | col[i].y -= adj * i + adj;
|
635 | }
|
636 | }
|
637 | }
|
638 | } // contract, expand, adjust
|
639 |
|
640 |
|
641 | let widths = [];
|
642 |
|
643 | for (let col of cols) {
|
644 | let min = [center - values.offset - values.pad];
|
645 | let max = [center + values.offset + values.pad];
|
646 |
|
647 | for (let item of col) {
|
648 | min.push(item.x - values.pad);
|
649 | max.push(item.x + item.width + values.pad);
|
650 | }
|
651 |
|
652 | min = Math.min(...min);
|
653 | max = Math.max(...max);
|
654 | let width = values.width;
|
655 | let adj = 0;
|
656 |
|
657 | if (!values.dynamic) {
|
658 | adj = center - parseInt((min + max) / 2);
|
659 | } else {
|
660 | width = max - min;
|
661 | adj = -min;
|
662 | }
|
663 |
|
664 | for (let item of col) {
|
665 | item.x += adj;
|
666 | }
|
667 |
|
668 | widths.push(width);
|
669 | }
|
670 |
|
671 | return {
|
672 | 'options': values,
|
673 | 'widths': widths,
|
674 | 'columns': cols
|
675 | };
|
676 | };
|
677 |
|
678 | /**
|
679 | * Array of numbers for kinds of symbols: writing, location, and punctuation.
|
680 | * @alias fsw.kind
|
681 | * @type {number[]}
|
682 | */
|
683 |
|
684 | const kind = [0x100, 0x37f, 0x387];
|
685 | /**
|
686 | * Array of numbers for categories of symbols: hand, movement, dynamics, head, trunk & limb, location, and punctuation.
|
687 | * @alias fsw.category
|
688 | * @type {number[]}
|
689 | */
|
690 |
|
691 | const category = [0x100, 0x205, 0x2f7, 0x2ff, 0x36d, 0x37f, 0x387];
|
692 | /**
|
693 | * Array of numbers for the 30 symbol groups.
|
694 | * @alias fsw.group
|
695 | * @type {number[]}
|
696 | */
|
697 |
|
698 | const 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];
|
699 | /**
|
700 | * Object of symbol ranges with starting and ending numbers.
|
701 | *
|
702 | * { all, writing, hand, movement, dynamic, head, hcenter, vcenter, trunk, limb, location, punctuation }
|
703 | * @alias fsw.ranges
|
704 | * @type {object}
|
705 | */
|
706 |
|
707 | const ranges = {
|
708 | 'all': [0x100, 0x38b],
|
709 | 'writing': [0x100, 0x37e],
|
710 | 'hand': [0x100, 0x204],
|
711 | 'movement': [0x205, 0x2f6],
|
712 | 'dynamic': [0x2f7, 0x2fe],
|
713 | 'head': [0x2ff, 0x36c],
|
714 | 'hcenter': [0x2ff, 0x36c],
|
715 | 'vcenter': [0x2ff, 0x375],
|
716 | 'trunk': [0x36d, 0x375],
|
717 | 'limb': [0x376, 0x37e],
|
718 | 'location': [0x37f, 0x386],
|
719 | 'punctuation': [0x387, 0x38b]
|
720 | };
|
721 | /**
|
722 | * Function to test if symbol is of a certain type.
|
723 | * @function fsw.isType
|
724 | * @param {string} key - an FSW symbol key
|
725 | * @param {string} type - the name of a symbol range
|
726 | * @returns {boolean} is symbol of specified type
|
727 | * @example
|
728 | * fsw.isType('S10000', 'hand')
|
729 | *
|
730 | * return true
|
731 | */
|
732 |
|
733 | const isType = (key, type) => {
|
734 | const parsed = parse.symbol(key);
|
735 |
|
736 | if (parsed.symbol) {
|
737 | const dec = parseInt(parsed.symbol.slice(1, 4), 16);
|
738 | const range = ranges[type];
|
739 |
|
740 | if (range) {
|
741 | return range[0] <= dec && range[1] >= dec;
|
742 | }
|
743 | }
|
744 |
|
745 | return false;
|
746 | };
|
747 |
|
748 | /**
|
749 | * Array of colors associated with the seven symbol categories.
|
750 | * @alias fsw.colors
|
751 | * @type {string[]}
|
752 | */
|
753 |
|
754 | const colors = ['#0000CC', '#CC0000', '#FF0099', '#006600', '#000000', '#884411', '#FF9900'];
|
755 | /**
|
756 | * Function that returns the standardized color for a symbol.
|
757 | * @function fsw.colorize
|
758 | * @param {string} key - an FSW symbol key
|
759 | * @returns {string} name of standardized color for symbol
|
760 | * @example
|
761 | * fsw.colorize('S10000')
|
762 | *
|
763 | * return '#0000CC'
|
764 | */
|
765 |
|
766 | const colorize = key => {
|
767 | const parsed = parse.symbol(key);
|
768 | let color = '#000000';
|
769 |
|
770 | if (parsed.symbol) {
|
771 | const dec = parseInt(parsed.symbol.slice(1, 4), 16);
|
772 | const index = category.findIndex(val => val > dec);
|
773 | color = colors[index < 0 ? 6 : index - 1];
|
774 | }
|
775 |
|
776 | return color;
|
777 | };
|
778 |
|
779 | exports.category = category;
|
780 | exports.colorize = colorize;
|
781 | exports.colors = colors;
|
782 | exports.columnDefaults = columnDefaults;
|
783 | exports.columnDefaultsMerge = columnDefaultsMerge;
|
784 | exports.columns = columns;
|
785 | exports.compose = compose;
|
786 | exports.group = group;
|
787 | exports.info = info;
|
788 | exports.isType = isType;
|
789 | exports.kind = kind;
|
790 | exports.parse = parse;
|
791 | exports.ranges = ranges;
|
792 | exports.re = re$1;
|
793 |
|
794 | Object.defineProperty(exports, '__esModule', { value: true });
|
795 |
|
796 | }));
|
797 |
|
798 | /* support ongoing development on https://patreon.com/signwriting */
|
799 | });
|
800 |
|
801 | export { fsw as f };
|