UNPKG

8.71 kBJavaScriptView Raw
1/**
2* Sutton SignWriting Core Module v1.3.1 (https://github.com/sutton-signwriting/core)
3* Author: Steve Slevinski (https://SteveSlevinski.me)
4* style.js is released under the MIT License.
5*/
6
7(function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9 typeof define === 'function' && define.amd ? define(['exports'], factory) :
10 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ssw = global.ssw || {}, global.ssw.style = {})));
11})(this, (function (exports) { 'use strict';
12
13 /**
14 * Object of regular expressions for style strings
15 *
16 * { colorize, colorhex, colorname, padding, zoom, zoomsym, classbase, id, colorbase, color, colors, background, detail, detailsym, classes, full }
17 * @alias style.re
18 * @type {object}
19 */
20 let re = {
21 'colorize': 'C',
22 'colorhex': '(?:[0-9a-fA-F]{3}){1,2}',
23 'colorname': '[a-zA-Z]+',
24 'padding': 'P[0-9]{2}',
25 'zoom': 'Z(?:[0-9]+(?:\\.[0-9]+)?|x)',
26 'zoomsym': 'Z[0-9]{2},[0-9]+(?:\\.[0-9]+)?(?:,[0-9]{3}x[0-9]{3})?',
27 'classbase': '-?[_a-zA-Z][_a-zA-Z0-9-]{0,100}',
28 'id': '[a-zA-Z][_a-zA-Z0-9-]{0,100}'
29 };
30 re.colorbase = `(?:${re.colorhex}|${re.colorname})`;
31 re.color = `_${re.colorbase}_`;
32 re.colors = `_${re.colorbase}(?:,${re.colorbase})?_`;
33 re.background = `G${re.color}`;
34 re.detail = `D${re.colors}`;
35 re.detailsym = `D[0-9]{2}${re.colors}`;
36 re.classes = `${re.classbase}(?: ${re.classbase})*`;
37 re.full = `-(${re.colorize})?(${re.padding})?(${re.background})?(${re.detail})?(${re.zoom})?(?:-((?:${re.detailsym})*)((?:${re.zoomsym})*))?(?:-(${re.classes})?!(?:(${re.id})!)?)?`;
38
39 const prefixColor = color => {
40 const regex = new RegExp(`^${re.colorhex}$`);
41 return (regex.test(color) ? '#' : '') + color;
42 };
43 /**
44 * Function to parse style string to object
45 * @function style.parse
46 * @param {string} styleString - a style string
47 * @returns {object} elements of style string
48 * @example
49 * style.parse('-CP10G_blue_D_red,Cyan_')
50 *
51 * return {
52 * 'colorize': true,
53 * 'padding': 10,
54 * 'background': 'blue',
55 * 'detail': ['red', 'Cyan']
56 * }
57 */
58
59
60 const parse = styleString => {
61 const regex = `^${re.full}`;
62 const m = (typeof styleString === 'string' ? styleString.match(new RegExp(regex)) : []) || [];
63 return {
64 'colorize': !m[1] ? undefined : !!m[1],
65 'padding': !m[2] ? undefined : parseInt(m[2].slice(1)),
66 'background': !m[3] ? undefined : prefixColor(m[3].slice(2, -1)),
67 'detail': !m[4] ? undefined : m[4].slice(2, -1).split(',').map(prefixColor),
68 'zoom': !m[5] ? undefined : m[5] === 'Zx' ? 'x' : parseFloat(m[5].slice(1)),
69 'detailsym': !m[6] ? undefined : m[6].match(new RegExp(re.detailsym, 'g')).map(val => {
70 const parts = val.split('_');
71 const detail = parts[1].split(',').map(prefixColor);
72 return {
73 'index': parseInt(parts[0].slice(1)),
74 'detail': detail
75 };
76 }),
77 'zoomsym': !m[7] ? undefined : m[7].match(new RegExp(re.zoomsym, 'g')).map(val => {
78 const parts = val.split(',');
79 return {
80 'index': parseInt(parts[0].slice(1)),
81 'zoom': parseFloat(parts[1]),
82 'offset': !parts[2] ? undefined : parts[2].split('x').map(val => parseInt(val) - 500)
83 };
84 }),
85 'classes': !m[8] ? undefined : m[8],
86 'id': !m[9] ? undefined : m[9]
87 };
88 };
89
90 /**
91 * Function to compose style string from object
92 * @function style.compose
93 * @param {object} styleObject - an object of style options
94 * @param {boolean} styleObject.colorize - boolean to use standardized colors for symbol groups
95 * @param {number} styleObject.padding - integer value for padding around symbol or sign
96 * @param {string} styleObject.background - css name or hex color for background
97 * @param {string[]} styleObject.detail - css name or hex color for line and optional fill
98 * @param {number} styleObject.zoom - decimal value for zoom level
99 * @param {{index:number,detail:string[]}[]} styleObject.detailsym - array of symbol indexes and detail color array
100 * @param {{index:number,zoom:number,offset:number[]}[]} styleObject.zoomsym - array of symbol indexes and zoom levels with optional x,y offset
101 * @param {string} styleObject.classes - list of class names separated with spaces used for SVG
102 * @param {string} styleObject.id - id name used for SVG
103 * @returns {string} style string
104 * @example
105 * style.compose({
106 * 'colorize': true,
107 * 'padding': 10,
108 * 'background': 'blue',
109 * 'detail': ['red', 'Cyan'],
110 * 'zoom': 1.1,
111 * 'detailsym': [
112 * {
113 * 'index': 1,
114 * 'detail': ['#ff00ff']
115 * },
116 * {
117 * 'index': 2,
118 * 'detail': ['yellow', 'green']
119 * }
120 * ],
121 * 'zoomsym': [
122 * {
123 * 'index': 1,
124 * 'zoom': 10,
125 * 'offset': [0, 0]
126 * },
127 * {
128 * 'index': 2,
129 * 'zoom': 5.5
130 * }
131 * ],
132 * 'classes': 'primary blinking',
133 * 'id': 'cursor'
134 * })
135 *
136 * return '-CP10G_blue_D_red,Cyan_Z1.1-D01_ff00ff_D02_yellow,green_Z01,10,500x500Z02,5.5-primary blinking!cursor!'
137 */
138
139 const compose = styleObject => {
140 if (typeof styleObject !== 'object' || styleObject === null) return undefined; // three sections
141
142 let style1 = '-';
143 style1 += !styleObject.colorize ? '' : 'C';
144 const padding = parseInt(styleObject.padding);
145 style1 += !padding || padding <= 0 || padding > 99 ? '' : 'P' + (padding > 9 ? padding : '0' + padding);
146 const background = !styleObject.background || !(typeof styleObject.background === 'string') ? undefined : styleObject.background.match(re.colorbase)[0];
147 style1 += !background ? '' : 'G_' + background + '_';
148 const detail1 = !styleObject.detail || !styleObject.detail[0] || !(typeof styleObject.detail[0] === 'string') ? undefined : styleObject.detail[0].match(re.colorbase)[0];
149 const detail2 = !styleObject.detail || !styleObject.detail[1] || !(typeof styleObject.detail[1] === 'string') ? undefined : styleObject.detail[1].match(re.colorbase)[0];
150
151 if (detail1) {
152 style1 += 'D_' + detail1;
153
154 if (detail2) {
155 style1 += ',' + detail2;
156 }
157
158 style1 += '_';
159 }
160
161 const zoom = styleObject.zoom === 'x' ? 'x' : parseFloat(styleObject.zoom);
162 style1 += !zoom || zoom <= 0 ? '' : 'Z' + zoom;
163 let style2 = '';
164 const detailsym = !styleObject.detailsym || !Array.isArray(styleObject.detailsym) ? [] : styleObject.detailsym.map(styleObject => {
165 const index = parseInt(styleObject.index);
166 if (!index || index <= 0 || index > 99) return '';
167 let style = 'D' + (index > 9 ? index : '0' + index);
168 const detail1 = !styleObject.detail || !styleObject.detail[0] ? undefined : styleObject.detail[0].match(re.colorbase)[0];
169 const detail2 = !styleObject.detail || !styleObject.detail[1] ? undefined : styleObject.detail[1].match(re.colorbase)[0];
170
171 if (detail1) {
172 style += '_' + detail1;
173
174 if (detail2) {
175 style += ',' + detail2;
176 }
177
178 style += '_';
179 }
180
181 return style;
182 });
183 style2 += detailsym.join('');
184 const zoomsym = !styleObject.zoomsym || !Array.isArray(styleObject.zoomsym) ? [] : styleObject.zoomsym.map(styleObject => {
185 const index = parseInt(styleObject.index);
186 if (!index || index <= 0 || index > 99) return '';
187 let style = 'Z' + (index > 9 ? index : '0' + index);
188 const zoom = parseFloat(styleObject.zoom);
189 style += !zoom || zoom <= 0 ? '' : ',' + zoom;
190
191 if (styleObject.offset && 0 in styleObject.offset && 1 in styleObject.offset) {
192 const x = parseInt(styleObject.offset[0]) + 500;
193 const y = parseInt(styleObject.offset[1]) + 500;
194
195 if (x >= 250 && x < 750 && y >= 250 && y < 750) {
196 style += ',' + x + 'x' + y;
197 }
198 }
199
200 return style;
201 });
202 style2 += zoomsym.join('');
203 let style3 = '';
204 const classes = !styleObject.classes || !(typeof styleObject.classes === 'string') ? undefined : styleObject.classes.match(re.classes)[0];
205 style3 += !classes ? '' : classes;
206 const id = !styleObject.id || !(typeof styleObject.id === 'string') ? undefined : styleObject.id.match(re.id)[0];
207 style3 += classes || id ? '!' : '';
208 style3 += !id ? '' : id + '!';
209 return style1 + (style2 || style3 ? '-' + style2 : '') + (style3 ? '-' + style3 : '');
210 };
211
212 exports.compose = compose;
213 exports.parse = parse;
214 exports.re = re;
215
216 Object.defineProperty(exports, '__esModule', { value: true });
217
218}));
219
220/* support ongoing development on https://patreon.com/signwriting */