UNPKG

6.17 kBJavaScriptView Raw
1import { parse } from './fsw-parse';
2import { info } from './fsw-info';
3
4const columnDefaults = {
5 'height': 500,
6 'width': 150,
7 'offset': 50,
8 'pad': 20,
9 'margin': 5,
10 'dynamic': false,
11 'background': undefined,
12 'punctuation': {
13 'spacing': true,
14 'pad': 30,
15 'pull': true
16 },
17 'style':{
18 'detail': ['black','white'],
19 'zoom': 1
20 }
21}
22
23
24/**
25 * Function to an object of column options with default values
26 *
27 * @function fsw.columnDefaultsMerge
28 * @param {ColumnOptions} options - object of column options
29 * @returns {ColumnOptions} object of column options merged with column defaults
30 * @example
31 * fsw.columnDefaultsMerge({height: 500,width:150})
32 *
33 * return {
34 * "height": 500,
35 * "width": 150,
36 * "offset": 50,
37 * "pad": 20,
38 * "margin": 5,
39 * "dynamic": false,
40 * "punctuation": {
41 * "spacing": true,
42 * "pad": 30,
43 * "pull": true
44 * },
45 * "style": {
46 * "detail": [
47 * "black",
48 * "white"
49 * ],
50 * "zoom": 1
51 * }
52 * }
53 */
54const columnDefaultsMerge = (options) => {
55 if (typeof options !== 'object') options = {};
56 return {
57 ...columnDefaults,
58 ...options,
59 punctuation: {
60 ...columnDefaults.punctuation,
61 ...options.punctuation
62 },
63 style: {
64 ...columnDefaults.style,
65 ...options.style
66 }
67 }
68}
69
70/**
71 * Function to transform an FSW text to an array of columns
72 *
73 * @function fsw.columns
74 * @param {string} fswText - FSW text of signs and punctuation
75 * @param {ColumnOptions} options - object of column options
76 * @returns {{options:ColumnOptions,widths:number[],columns:ColumnData}} object of column options, widths array, and column data
77 * @example
78 * fsw.columns('AS14c20S27106M518x529S14c20481x471S27106503x489 AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468 S38800464x496', {height: 500,width:150})
79 *
80 * return {
81 * "options": {
82 * "height": 500,
83 * "width": 150,
84 * "offset": 50,
85 * "pad": 20,
86 * "margin": 5,
87 * "dynamic": false,
88 * "punctuation": {
89 * "spacing": true,
90 * "pad": 30,
91 * "pull": true
92 * },
93 * "style": {
94 * "detail": [
95 * "black",
96 * "white"
97 * ],
98 * "zoom": 1
99 * }
100 * },
101 * "widths": [
102 * 150
103 * ],
104 * "columns": [
105 * [
106 * {
107 * "x": 56,
108 * "y": 20,
109 * "minX": 481,
110 * "minY": 471,
111 * "width": 37,
112 * "height": 58,
113 * "lane": 0,
114 * "padding": 0,
115 * "segment": "sign",
116 * "text": "AS14c20S27106M518x529S14c20481x471S27106503x489",
117 * "zoom": 1
118 * },
119 * {
120 * "x": 57,
121 * "y": 118,
122 * "minX": 482,
123 * "minY": 468,
124 * "width": 36,
125 * "height": 65,
126 * "lane": 0,
127 * "padding": 0,
128 * "segment": "sign",
129 * "text": "AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468",
130 * "zoom": 1
131 * },
132 * {
133 * "x": 39,
134 * "y": 203,
135 * "minX": 464,
136 * "minY": 496,
137 * "width": 72,
138 * "height": 8,
139 * "lane": 0,
140 * "padding": 0,
141 * "segment": "symbol",
142 * "text": "S38800464x496",
143 * "zoom": 1
144 * }
145 * ]
146 * ]
147 * }
148 */
149const columns = (fswText, options) => {
150 if (typeof fswText !== 'string') return {};
151 const values = columnDefaultsMerge(options);
152
153 let input = parse.text(fswText);
154 let cursor = 0;
155 let cols = [];
156 let col = [];
157 let plus = 0;
158 let center = parseInt(values.width/2);
159 let maxHeight = values.height - values.margin;
160 let pullable = true;
161 let finalize = false;
162
163 for (let val of input) {
164 let informed = info(val);
165 cursor += plus;
166 if (values.punctuation.spacing){
167 cursor += ((informed.segment=='sign')?values.pad:0);
168 } else {
169 cursor += values.pad;
170 }
171
172 finalize = ((cursor + informed.height) > maxHeight);
173
174 if (finalize && informed.segment=='symbol' && values.punctuation.pull && pullable){
175 finalize = false;
176 pullable = false;
177 }
178
179 if (col.length == 0) { finalize = false; }
180
181 if ( finalize) {
182 cursor = values.pad;
183 cols.push(col);
184 col = [];
185 pullable = true;
186 }
187 col.push(Object.assign(informed,{
188 x: center + (values.offset * informed.lane) - ((500-informed.minX) * informed.zoom * values.style.zoom),
189 y: cursor,
190 text: val
191 }))
192 cursor += (informed.height * informed.zoom * values.style.zoom);
193 if (values.punctuation.spacing){
194 plus = (informed.segment=='sign')?values.pad:values.punctuation.pad;
195 } else {
196 plus = values.pad;
197 }
198 }
199
200 if (col.length) {
201 cols.push(col);
202 }
203
204 // over height issue when pulling punctuation
205 if (values.punctuation.pull) {
206 for (let col of cols){
207 let last = col[col.length -1];
208 let diff = (last.y + last.height) - (values.height - values.margin);
209 if (diff>0){
210 let adj = parseInt(diff/(col.length)) + 1;
211 for (let i in col){
212 col[i].y -= adj*i + adj;
213 }
214 }
215 }
216 }
217
218 // contract, expand, adjust
219 let widths = [];
220 for (let col of cols){
221 let min = [(center - values.offset - values.pad)]
222 let max = [(center + values.offset + values.pad)]
223 for (let item of col){
224 min.push(item.x - values.pad);
225 max.push(item.x + item.width + values.pad);
226 }
227 min = Math.min(...min);
228 max = Math.max(...max);
229
230 let width = values.width;
231 let adj = 0;
232
233 if (!values.dynamic){
234 adj = center - parseInt((min + max)/2);
235 } else {
236 width = max - min;
237 adj = -min;
238 }
239 for (let item of col){
240 item.x += adj;
241 }
242 widths.push(width);
243 }
244
245 return {
246 'options': values,
247 'widths': widths,
248 'columns': cols
249 };
250}
251
252export { columnDefaults, columnDefaultsMerge, columns }
\No newline at end of file