1
+ /**
2
+ * Fork https://github.com/egoist/docute/blob/master/src/utils/yaml.js
3
+ */
4
+ /* eslint-disable */
5
+ /*
6
+ YAML parser for Javascript
7
+ Author: Diogo Costa
8
+ This program is released under the MIT License as follows:
9
+ Copyright (c) 2011 Diogo Costa (costa.h4evr@gmail.com)
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+ The above copyright notice and this permission notice shall be included in
17
+ all copies or substantial portions of the Software.
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ THE SOFTWARE.
25
+ */
26
+
27
+ /**
28
+ * @name YAML
29
+ * @namespace
30
+ */
31
+
32
+
33
+ var errors = [ ] ,
34
+ reference_blocks = [ ] ,
35
+ processing_time = 0 ,
36
+ regex =
37
+ {
38
+ "regLevel" : new RegExp ( "^([\\s\\-]+)" ) ,
39
+ "invalidLine" : new RegExp ( "^\\-\\-\\-|^\\.\\.\\.|^\\s*#.*|^\\s*$" ) ,
40
+ "dashesString" : new RegExp ( "^\\s*\\\"([^\\\"]*)\\\"\\s*$" ) ,
41
+ "quotesString" : new RegExp ( "^\\s*\\\'([^\\\']*)\\\'\\s*$" ) ,
42
+ "float" : new RegExp ( "^[+-]?[0-9]+\\.[0-9]+(e[+-]?[0-9]+(\\.[0-9]+)?)?$" ) ,
43
+ "integer" : new RegExp ( "^[+-]?[0-9]+$" ) ,
44
+ "array" : new RegExp ( "\\[\\s*(.*)\\s*\\]" ) ,
45
+ "map" : new RegExp ( "\\{\\s*(.*)\\s*\\}" ) ,
46
+ "key_value" : new RegExp ( "([a-z0-9_-][ a-z0-9_-]*):( .+)" , "i" ) ,
47
+ "single_key_value" : new RegExp ( "^([a-z0-9_-][ a-z0-9_-]*):( .+?)$" , "i" ) ,
48
+ "key" : new RegExp ( "([a-z0-9_-][ a-z0-9_-]+):( .+)?" , "i" ) ,
49
+ "item" : new RegExp ( "^-\\s+" ) ,
50
+ "trim" : new RegExp ( "^\\s+|\\s+$" ) ,
51
+ "comment" : new RegExp ( "([^\\\'\\\"#]+([\\\'\\\"][^\\\'\\\"]*[\\\'\\\"])*)*(#.*)?" )
52
+ } ;
53
+
54
+ /**
55
+ * @class A block of lines of a given level.
56
+ * @param {int } lvl The block's level.
57
+ * @private
58
+ */
59
+ function Block ( lvl ) {
60
+ return {
61
+ /* The block's parent */
62
+ parent : null ,
63
+ /* Number of children */
64
+ length : 0 ,
65
+ /* Block's level */
66
+ level : lvl ,
67
+ /* Lines of code to process */
68
+ lines : [ ] ,
69
+ /* Blocks with greater level */
70
+ children : [ ] ,
71
+ /* Add a block to the children collection */
72
+ addChild : function ( obj ) {
73
+ this . children . push ( obj ) ;
74
+ obj . parent = this ;
75
+ ++ this . length ;
76
+ }
77
+ } ;
78
+ }
79
+
80
+ // function to create an XMLHttpClient in a cross-browser manner
81
+ function createXMLHTTPRequest ( ) {
82
+ var xmlhttp ;
83
+
84
+ try {
85
+ // Mozilla / Safari / IE7
86
+ xmlhttp = new XMLHttpRequest ( ) ;
87
+ } catch ( e ) {
88
+ // IE
89
+ var XMLHTTP_IDS = new Array ( 'MSXML2.XMLHTTP.5.0' ,
90
+ 'MSXML2.XMLHTTP.4.0' ,
91
+ 'MSXML2.XMLHTTP.3.0' ,
92
+ 'MSXML2.XMLHTTP' ,
93
+ 'Microsoft.XMLHTTP' ) ;
94
+ var success = false ;
95
+ for ( var i = 0 ; i < XMLHTTP_IDS . length && ! success ; i ++ ) {
96
+ try {
97
+ xmlhttp = new ActiveXObject ( XMLHTTP_IDS [ i ] ) ;
98
+ success = true ;
99
+ } catch ( e ) { }
100
+ }
101
+ if ( ! success ) {
102
+ throw new Error ( 'Unable to create XMLHttpRequest.' ) ;
103
+ }
104
+ }
105
+
106
+ return xmlhttp ;
107
+ }
108
+
109
+ function parser ( str ) {
110
+ var regLevel = regex [ "regLevel" ] ;
111
+ var invalidLine = regex [ "invalidLine" ] ;
112
+ var lines = str . split ( "\n" ) ;
113
+ var m ;
114
+ var level = 0 , curLevel = 0 ;
115
+
116
+ var blocks = [ ] ;
117
+
118
+ var result = new Block ( - 1 ) ;
119
+ var currentBlock = new Block ( 0 ) ;
120
+ result . addChild ( currentBlock ) ;
121
+ var levels = [ ] ;
122
+ var line = "" ;
123
+
124
+ blocks . push ( currentBlock ) ;
125
+ levels . push ( level ) ;
126
+
127
+ for ( var i = 0 , len = lines . length ; i < len ; ++ i ) {
128
+ line = lines [ i ] ;
129
+
130
+ if ( line . match ( invalidLine ) ) {
131
+ continue ;
132
+ }
133
+
134
+ if ( m = regLevel . exec ( line ) ) {
135
+ level = m [ 1 ] . length ;
136
+ } else
137
+ level = 0 ;
138
+
139
+ if ( level > curLevel ) {
140
+ var oldBlock = currentBlock ;
141
+ currentBlock = new Block ( level ) ;
142
+ oldBlock . addChild ( currentBlock ) ;
143
+ blocks . push ( currentBlock ) ;
144
+ levels . push ( level ) ;
145
+ } else if ( level < curLevel ) {
146
+ var added = false ;
147
+
148
+ var k = levels . length - 1 ;
149
+ for ( ; k >= 0 ; -- k ) {
150
+ if ( levels [ k ] == level ) {
151
+ currentBlock = new Block ( level ) ;
152
+ blocks . push ( currentBlock ) ;
153
+ levels . push ( level ) ;
154
+ if ( blocks [ k ] . parent != null )
155
+ blocks [ k ] . parent . addChild ( currentBlock ) ;
156
+ added = true ;
157
+ break ;
158
+ }
159
+ }
160
+
161
+ if ( ! added ) {
162
+ errors . push ( "Error: Invalid indentation at line " + i + ": " + line ) ;
163
+ return ;
164
+ }
165
+ }
166
+
167
+ currentBlock . lines . push ( line . replace ( regex [ "trim" ] , "" ) ) ;
168
+ curLevel = level ;
169
+ }
170
+
171
+ return result ;
172
+ }
173
+
174
+ function processValue ( val ) {
175
+ val = val . replace ( regex [ "trim" ] , "" ) ;
176
+ var m = null ;
177
+
178
+ if ( val == 'true' ) {
179
+ return true ;
180
+ } else if ( val == 'false' ) {
181
+ return false ;
182
+ } else if ( val == '.NaN' ) {
183
+ return Number . NaN ;
184
+ } else if ( val == 'null' ) {
185
+ return null ;
186
+ } else if ( val == '.inf' ) {
187
+ return Number . POSITIVE_INFINITY ;
188
+ } else if ( val == '-.inf' ) {
189
+ return Number . NEGATIVE_INFINITY ;
190
+ } else if ( m = val . match ( regex [ "dashesString" ] ) ) {
191
+ return m [ 1 ] ;
192
+ } else if ( m = val . match ( regex [ "quotesString" ] ) ) {
193
+ return m [ 1 ] ;
194
+ } else if ( m = val . match ( regex [ "float" ] ) ) {
195
+ return parseFloat ( m [ 0 ] ) ;
196
+ } else if ( m = val . match ( regex [ "integer" ] ) ) {
197
+ return parseInt ( m [ 0 ] ) ;
198
+ } else if ( ! isNaN ( m = Date . parse ( val ) ) ) {
199
+ return new Date ( m ) ;
200
+ } else if ( m = val . match ( regex [ "single_key_value" ] ) ) {
201
+ var res = { } ;
202
+ res [ m [ 1 ] ] = processValue ( m [ 2 ] ) ;
203
+ return res ;
204
+ } else if ( m = val . match ( regex [ "array" ] ) ) {
205
+ var count = 0 , c = ' ' ;
206
+ var res = [ ] ;
207
+ var content = "" ;
208
+ var str = false ;
209
+ for ( var j = 0 , lenJ = m [ 1 ] . length ; j < lenJ ; ++ j ) {
210
+ c = m [ 1 ] [ j ] ;
211
+ if ( c == '\'' || c == '"' ) {
212
+ if ( str === false ) {
213
+ str = c ;
214
+ content += c ;
215
+ continue ;
216
+ } else if ( ( c == '\'' && str == '\'' ) || ( c == '"' && str == '"' ) ) {
217
+ str = false ;
218
+ content += c ;
219
+ continue ;
220
+ }
221
+ } else if ( str === false && ( c == '[' || c == '{' ) ) {
222
+ ++ count ;
223
+ } else if ( str === false && ( c == ']' || c == '}' ) ) {
224
+ -- count ;
225
+ } else if ( str === false && count == 0 && c == ',' ) {
226
+ res . push ( processValue ( content ) ) ;
227
+ content = "" ;
228
+ continue ;
229
+ }
230
+
231
+ content += c ;
232
+ }
233
+
234
+ if ( content . length > 0 )
235
+ res . push ( processValue ( content ) ) ;
236
+ return res ;
237
+ } else if ( m = val . match ( regex [ "map" ] ) ) {
238
+ var count = 0 , c = ' ' ;
239
+ var res = [ ] ;
240
+ var content = "" ;
241
+ var str = false ;
242
+ for ( var j = 0 , lenJ = m [ 1 ] . length ; j < lenJ ; ++ j ) {
243
+ c = m [ 1 ] [ j ] ;
244
+ if ( c == '\'' || c == '"' ) {
245
+ if ( str === false ) {
246
+ str = c ;
247
+ content += c ;
248
+ continue ;
249
+ } else if ( ( c == '\'' && str == '\'' ) || ( c == '"' && str == '"' ) ) {
250
+ str = false ;
251
+ content += c ;
252
+ continue ;
253
+ }
254
+ } else if ( str === false && ( c == '[' || c == '{' ) ) {
255
+ ++ count ;
256
+ } else if ( str === false && ( c == ']' || c == '}' ) ) {
257
+ -- count ;
258
+ } else if ( str === false && count == 0 && c == ',' ) {
259
+ res . push ( content ) ;
260
+ content = "" ;
261
+ continue ;
262
+ }
263
+
264
+ content += c ;
265
+ }
266
+
267
+ if ( content . length > 0 )
268
+ res . push ( content ) ;
269
+
270
+ var newRes = { } ;
271
+ for ( var j = 0 , lenJ = res . length ; j < lenJ ; ++ j ) {
272
+ if ( m = res [ j ] . match ( regex [ "key_value" ] ) ) {
273
+ newRes [ m [ 1 ] ] = processValue ( m [ 2 ] ) ;
274
+ }
275
+ }
276
+
277
+ return newRes ;
278
+ } else
279
+ return val ;
280
+ }
281
+
282
+ function processFoldedBlock ( block ) {
283
+ var lines = block . lines ;
284
+ var children = block . children ;
285
+ var str = lines . join ( " " ) ;
286
+ var chunks = [ str ] ;
287
+ for ( var i = 0 , len = children . length ; i < len ; ++ i ) {
288
+ chunks . push ( processFoldedBlock ( children [ i ] ) ) ;
289
+ }
290
+ return chunks . join ( "\n" ) ;
291
+ }
292
+
293
+ function processLiteralBlock ( block ) {
294
+ var lines = block . lines ;
295
+ var children = block . children ;
296
+ var str = lines . join ( "\n" ) ;
297
+ for ( var i = 0 , len = children . length ; i < len ; ++ i ) {
298
+ str += processLiteralBlock ( children [ i ] ) ;
299
+ }
300
+ return str ;
301
+ }
302
+
303
+ function processBlock ( blocks ) {
304
+ var m = null ;
305
+ var res = { } ;
306
+ var lines = null ;
307
+ var children = null ;
308
+ var currentObj = null ;
309
+
310
+ var level = - 1 ;
311
+
312
+ var processedBlocks = [ ] ;
313
+
314
+ var isMap = true ;
315
+
316
+ for ( var j = 0 , lenJ = blocks . length ; j < lenJ ; ++ j ) {
317
+
318
+ if ( level != - 1 && level != blocks [ j ] . level )
319
+ continue ;
320
+
321
+ processedBlocks . push ( j ) ;
322
+
323
+ level = blocks [ j ] . level ;
324
+ lines = blocks [ j ] . lines ;
325
+ children = blocks [ j ] . children ;
326
+ currentObj = null ;
327
+
328
+ for ( var i = 0 , len = lines . length ; i < len ; ++ i ) {
329
+ var line = lines [ i ] ;
330
+
331
+ if ( m = line . match ( regex [ "key" ] ) ) {
332
+ var key = m [ 1 ] ;
333
+
334
+ if ( key [ 0 ] == '-' ) {
335
+ key = key . replace ( regex [ "item" ] , "" ) ;
336
+ if ( isMap ) {
337
+ isMap = false ;
338
+ if ( typeof ( res . length ) === "undefined" ) {
339
+ res = [ ] ;
340
+ }
341
+ }
342
+ if ( currentObj != null ) res . push ( currentObj ) ;
343
+ currentObj = { } ;
344
+ isMap = true ;
345
+ }
346
+
347
+ if ( typeof m [ 2 ] != "undefined" ) {
348
+ var value = m [ 2 ] . replace ( regex [ "trim" ] , "" ) ;
349
+ if ( value [ 0 ] == '&' ) {
350
+ var nb = processBlock ( children ) ;
351
+ if ( currentObj != null ) currentObj [ key ] = nb ;
352
+ else res [ key ] = nb ;
353
+ reference_blocks [ value . substr ( 1 ) ] = nb ;
354
+ } else if ( value [ 0 ] == '|' ) {
355
+ if ( currentObj != null ) currentObj [ key ] = processLiteralBlock ( children . shift ( ) ) ;
356
+ else res [ key ] = processLiteralBlock ( children . shift ( ) ) ;
357
+ } else if ( value [ 0 ] == '*' ) {
358
+ var v = value . substr ( 1 ) ;
359
+ var no = { } ;
360
+
361
+ if ( typeof reference_blocks [ v ] == "undefined" ) {
362
+ errors . push ( "Reference '" + v + "' not found!" ) ;
363
+ } else {
364
+ for ( var k in reference_blocks [ v ] ) {
365
+ no [ k ] = reference_blocks [ v ] [ k ] ;
366
+ }
367
+
368
+ if ( currentObj != null ) currentObj [ key ] = no ;
369
+ else res [ key ] = no ;
370
+ }
371
+ } else if ( value [ 0 ] == '>' ) {
372
+ if ( currentObj != null ) currentObj [ key ] = processFoldedBlock ( children . shift ( ) ) ;
373
+ else res [ key ] = processFoldedBlock ( children . shift ( ) ) ;
374
+ } else {
375
+ if ( currentObj != null ) currentObj [ key ] = processValue ( value ) ;
376
+ else res [ key ] = processValue ( value ) ;
377
+ }
378
+ } else {
379
+ if ( currentObj != null ) currentObj [ key ] = processBlock ( children ) ;
380
+ else res [ key ] = processBlock ( children ) ;
381
+ }
382
+ } else if ( line . match ( / ^ - \s * $ / ) ) {
383
+ if ( isMap ) {
384
+ isMap = false ;
385
+ if ( typeof ( res . length ) === "undefined" ) {
386
+ res = [ ] ;
387
+ }
388
+ }
389
+ if ( currentObj != null ) res . push ( currentObj ) ;
390
+ currentObj = { } ;
391
+ isMap = true ;
392
+ continue ;
393
+ } else if ( m = line . match ( / ^ - \s * ( .* ) / ) ) {
394
+ if ( currentObj != null )
395
+ currentObj . push ( processValue ( m [ 1 ] ) ) ;
396
+ else {
397
+ if ( isMap ) {
398
+ isMap = false ;
399
+ if ( typeof ( res . length ) === "undefined" ) {
400
+ res = [ ] ;
401
+ }
402
+ }
403
+ res . push ( processValue ( m [ 1 ] ) ) ;
404
+ }
405
+ continue ;
406
+ }
407
+ }
408
+
409
+ if ( currentObj != null ) {
410
+ if ( isMap ) {
411
+ isMap = false ;
412
+ if ( typeof ( res . length ) === "undefined" ) {
413
+ res = [ ] ;
414
+ }
415
+ }
416
+ res . push ( currentObj ) ;
417
+ }
418
+ }
419
+
420
+ for ( var j = processedBlocks . length - 1 ; j >= 0 ; -- j ) {
421
+ blocks . splice . call ( blocks , processedBlocks [ j ] , 1 ) ;
422
+ }
423
+
424
+ return res ;
425
+ }
426
+
427
+ function semanticAnalysis ( blocks ) {
428
+ var res = processBlock ( blocks . children ) ;
429
+ return res ;
430
+ }
431
+
432
+ function preProcess ( src ) {
433
+ var m ;
434
+ var lines = src . split ( "\n" ) ;
435
+
436
+ var r = regex [ "comment" ] ;
437
+
438
+ for ( var i in lines ) {
439
+ if ( m = lines [ i ] . match ( r ) ) {
440
+ /* var cmt = "";
441
+ if(typeof m[3] != "undefined")
442
+ lines[i] = m[1];
443
+ else if(typeof m[3] != "undefined")
444
+ lines[i] = m[3];
445
+ else
446
+ lines[i] = "";
447
+ */
448
+ if ( typeof m [ 3 ] !== "undefined" ) {
449
+ lines [ i ] = m [ 0 ] . substr ( 0 , m [ 0 ] . length - m [ 3 ] . length ) ;
450
+ }
451
+ }
452
+ }
453
+
454
+ return lines . join ( "\n" ) ;
455
+ }
456
+
457
+ function load ( str ) {
458
+ errors = [ ] ;
459
+ reference_blocks = [ ] ;
460
+ processing_time = ( new Date ( ) ) . getTime ( ) ;
461
+ var pre = preProcess ( str )
462
+ var doc = parser ( pre ) ;
463
+ var res = semanticAnalysis ( doc ) ;
464
+ processing_time = ( new Date ( ) ) . getTime ( ) - processing_time ;
465
+
466
+ return res ;
467
+ }
468
+
469
+ export default load
0 commit comments