1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 | var common = require('./common');
|
6 | var YAMLException = require('./exception');
|
7 | var DEFAULT_SCHEMA = require('./schema/default');
|
8 |
|
9 | var _toString = Object.prototype.toString;
|
10 | var _hasOwnProperty = Object.prototype.hasOwnProperty;
|
11 |
|
12 | var CHAR_BOM = 0xFEFF;
|
13 | var CHAR_TAB = 0x09;
|
14 | var CHAR_LINE_FEED = 0x0A;
|
15 | var CHAR_CARRIAGE_RETURN = 0x0D;
|
16 | var CHAR_SPACE = 0x20;
|
17 | var CHAR_EXCLAMATION = 0x21;
|
18 | var CHAR_DOUBLE_QUOTE = 0x22;
|
19 | var CHAR_SHARP = 0x23;
|
20 | var CHAR_PERCENT = 0x25;
|
21 | var CHAR_AMPERSAND = 0x26;
|
22 | var CHAR_SINGLE_QUOTE = 0x27;
|
23 | var CHAR_ASTERISK = 0x2A;
|
24 | var CHAR_COMMA = 0x2C;
|
25 | var CHAR_MINUS = 0x2D;
|
26 | var CHAR_COLON = 0x3A;
|
27 | var CHAR_EQUALS = 0x3D;
|
28 | var CHAR_GREATER_THAN = 0x3E;
|
29 | var CHAR_QUESTION = 0x3F;
|
30 | var CHAR_COMMERCIAL_AT = 0x40;
|
31 | var CHAR_LEFT_SQUARE_BRACKET = 0x5B;
|
32 | var CHAR_RIGHT_SQUARE_BRACKET = 0x5D;
|
33 | var CHAR_GRAVE_ACCENT = 0x60;
|
34 | var CHAR_LEFT_CURLY_BRACKET = 0x7B;
|
35 | var CHAR_VERTICAL_LINE = 0x7C;
|
36 | var CHAR_RIGHT_CURLY_BRACKET = 0x7D;
|
37 |
|
38 | var ESCAPE_SEQUENCES = {};
|
39 |
|
40 | ESCAPE_SEQUENCES[0x00] = '\\0';
|
41 | ESCAPE_SEQUENCES[0x07] = '\\a';
|
42 | ESCAPE_SEQUENCES[0x08] = '\\b';
|
43 | ESCAPE_SEQUENCES[0x09] = '\\t';
|
44 | ESCAPE_SEQUENCES[0x0A] = '\\n';
|
45 | ESCAPE_SEQUENCES[0x0B] = '\\v';
|
46 | ESCAPE_SEQUENCES[0x0C] = '\\f';
|
47 | ESCAPE_SEQUENCES[0x0D] = '\\r';
|
48 | ESCAPE_SEQUENCES[0x1B] = '\\e';
|
49 | ESCAPE_SEQUENCES[0x22] = '\\"';
|
50 | ESCAPE_SEQUENCES[0x5C] = '\\\\';
|
51 | ESCAPE_SEQUENCES[0x85] = '\\N';
|
52 | ESCAPE_SEQUENCES[0xA0] = '\\_';
|
53 | ESCAPE_SEQUENCES[0x2028] = '\\L';
|
54 | ESCAPE_SEQUENCES[0x2029] = '\\P';
|
55 |
|
56 | var DEPRECATED_BOOLEANS_SYNTAX = [
|
57 | 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
|
58 | 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
|
59 | ];
|
60 |
|
61 | var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;
|
62 |
|
63 | function compileStyleMap(schema, map) {
|
64 | var result, keys, index, length, tag, style, type;
|
65 |
|
66 | if (map === null) return {};
|
67 |
|
68 | result = {};
|
69 | keys = Object.keys(map);
|
70 |
|
71 | for (index = 0, length = keys.length; index < length; index += 1) {
|
72 | tag = keys[index];
|
73 | style = String(map[tag]);
|
74 |
|
75 | if (tag.slice(0, 2) === '!!') {
|
76 | tag = 'tag:yaml.org,2002:' + tag.slice(2);
|
77 | }
|
78 | type = schema.compiledTypeMap['fallback'][tag];
|
79 |
|
80 | if (type && _hasOwnProperty.call(type.styleAliases, style)) {
|
81 | style = type.styleAliases[style];
|
82 | }
|
83 |
|
84 | result[tag] = style;
|
85 | }
|
86 |
|
87 | return result;
|
88 | }
|
89 |
|
90 | function encodeHex(character) {
|
91 | var string, handle, length;
|
92 |
|
93 | string = character.toString(16).toUpperCase();
|
94 |
|
95 | if (character <= 0xFF) {
|
96 | handle = 'x';
|
97 | length = 2;
|
98 | } else if (character <= 0xFFFF) {
|
99 | handle = 'u';
|
100 | length = 4;
|
101 | } else if (character <= 0xFFFFFFFF) {
|
102 | handle = 'U';
|
103 | length = 8;
|
104 | } else {
|
105 | throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
|
106 | }
|
107 |
|
108 | return '\\' + handle + common.repeat('0', length - string.length) + string;
|
109 | }
|
110 |
|
111 |
|
112 | var QUOTING_TYPE_SINGLE = 1,
|
113 | QUOTING_TYPE_DOUBLE = 2;
|
114 |
|
115 | function State(options) {
|
116 | this.schema = options['schema'] || DEFAULT_SCHEMA;
|
117 | this.indent = Math.max(1, (options['indent'] || 2));
|
118 | this.noArrayIndent = options['noArrayIndent'] || false;
|
119 | this.skipInvalid = options['skipInvalid'] || false;
|
120 | this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
|
121 | this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
|
122 | this.sortKeys = options['sortKeys'] || false;
|
123 | this.lineWidth = options['lineWidth'] || 80;
|
124 | this.noRefs = options['noRefs'] || false;
|
125 | this.noCompatMode = options['noCompatMode'] || false;
|
126 | this.condenseFlow = options['condenseFlow'] || false;
|
127 | this.quotingType = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
|
128 | this.forceQuotes = options['forceQuotes'] || false;
|
129 | this.replacer = typeof options['replacer'] === 'function' ? options['replacer'] : null;
|
130 |
|
131 | this.implicitTypes = this.schema.compiledImplicit;
|
132 | this.explicitTypes = this.schema.compiledExplicit;
|
133 |
|
134 | this.tag = null;
|
135 | this.result = '';
|
136 |
|
137 | this.duplicates = [];
|
138 | this.usedDuplicates = null;
|
139 | }
|
140 |
|
141 |
|
142 | function indentString(string, spaces) {
|
143 | var ind = common.repeat(' ', spaces),
|
144 | position = 0,
|
145 | next = -1,
|
146 | result = '',
|
147 | line,
|
148 | length = string.length;
|
149 |
|
150 | while (position < length) {
|
151 | next = string.indexOf('\n', position);
|
152 | if (next === -1) {
|
153 | line = string.slice(position);
|
154 | position = length;
|
155 | } else {
|
156 | line = string.slice(position, next + 1);
|
157 | position = next + 1;
|
158 | }
|
159 |
|
160 | if (line.length && line !== '\n') result += ind;
|
161 |
|
162 | result += line;
|
163 | }
|
164 |
|
165 | return result;
|
166 | }
|
167 |
|
168 | function generateNextLine(state, level) {
|
169 | return '\n' + common.repeat(' ', state.indent * level);
|
170 | }
|
171 |
|
172 | function testImplicitResolving(state, str) {
|
173 | var index, length, type;
|
174 |
|
175 | for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
|
176 | type = state.implicitTypes[index];
|
177 |
|
178 | if (type.resolve(str)) {
|
179 | return true;
|
180 | }
|
181 | }
|
182 |
|
183 | return false;
|
184 | }
|
185 |
|
186 |
|
187 | function isWhitespace(c) {
|
188 | return c === CHAR_SPACE || c === CHAR_TAB;
|
189 | }
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 | function isPrintable(c) {
|
196 | return (0x00020 <= c && c <= 0x00007E)
|
197 | || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
|
198 | || ((0x0E000 <= c && c <= 0x00FFFD) && c !== CHAR_BOM)
|
199 | || (0x10000 <= c && c <= 0x10FFFF);
|
200 | }
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 | function isNsCharOrWhitespace(c) {
|
208 | return isPrintable(c)
|
209 | && c !== CHAR_BOM
|
210 |
|
211 | && c !== CHAR_CARRIAGE_RETURN
|
212 | && c !== CHAR_LINE_FEED;
|
213 | }
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | function isPlainSafe(c, prev, inblock) {
|
225 | var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
|
226 | var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
|
227 | return (
|
228 |
|
229 | inblock ?
|
230 | cIsNsCharOrWhitespace
|
231 | : cIsNsCharOrWhitespace
|
232 |
|
233 | && c !== CHAR_COMMA
|
234 | && c !== CHAR_LEFT_SQUARE_BRACKET
|
235 | && c !== CHAR_RIGHT_SQUARE_BRACKET
|
236 | && c !== CHAR_LEFT_CURLY_BRACKET
|
237 | && c !== CHAR_RIGHT_CURLY_BRACKET
|
238 | )
|
239 |
|
240 | && c !== CHAR_SHARP
|
241 | && !(prev === CHAR_COLON && !cIsNsChar)
|
242 | || (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP)
|
243 | || (prev === CHAR_COLON && cIsNsChar);
|
244 | }
|
245 |
|
246 |
|
247 | function isPlainSafeFirst(c) {
|
248 |
|
249 |
|
250 |
|
251 | return isPrintable(c) && c !== CHAR_BOM
|
252 | && !isWhitespace(c)
|
253 |
|
254 |
|
255 | && c !== CHAR_MINUS
|
256 | && c !== CHAR_QUESTION
|
257 | && c !== CHAR_COLON
|
258 | && c !== CHAR_COMMA
|
259 | && c !== CHAR_LEFT_SQUARE_BRACKET
|
260 | && c !== CHAR_RIGHT_SQUARE_BRACKET
|
261 | && c !== CHAR_LEFT_CURLY_BRACKET
|
262 | && c !== CHAR_RIGHT_CURLY_BRACKET
|
263 |
|
264 | && c !== CHAR_SHARP
|
265 | && c !== CHAR_AMPERSAND
|
266 | && c !== CHAR_ASTERISK
|
267 | && c !== CHAR_EXCLAMATION
|
268 | && c !== CHAR_VERTICAL_LINE
|
269 | && c !== CHAR_EQUALS
|
270 | && c !== CHAR_GREATER_THAN
|
271 | && c !== CHAR_SINGLE_QUOTE
|
272 | && c !== CHAR_DOUBLE_QUOTE
|
273 |
|
274 | && c !== CHAR_PERCENT
|
275 | && c !== CHAR_COMMERCIAL_AT
|
276 | && c !== CHAR_GRAVE_ACCENT;
|
277 | }
|
278 |
|
279 |
|
280 | function isPlainSafeLast(c) {
|
281 |
|
282 | return !isWhitespace(c) && c !== CHAR_COLON;
|
283 | }
|
284 |
|
285 |
|
286 | function codePointAt(string, pos) {
|
287 | var first = string.charCodeAt(pos), second;
|
288 | if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {
|
289 | second = string.charCodeAt(pos + 1);
|
290 | if (second >= 0xDC00 && second <= 0xDFFF) {
|
291 |
|
292 | return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
|
293 | }
|
294 | }
|
295 | return first;
|
296 | }
|
297 |
|
298 |
|
299 | function needIndentIndicator(string) {
|
300 | var leadingSpaceRe = /^\n* /;
|
301 | return leadingSpaceRe.test(string);
|
302 | }
|
303 |
|
304 | var STYLE_PLAIN = 1,
|
305 | STYLE_SINGLE = 2,
|
306 | STYLE_LITERAL = 3,
|
307 | STYLE_FOLDED = 4,
|
308 | STYLE_DOUBLE = 5;
|
309 |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 |
|
315 |
|
316 |
|
317 | function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth,
|
318 | testAmbiguousType, quotingType, forceQuotes, inblock) {
|
319 |
|
320 | var i;
|
321 | var char = 0;
|
322 | var prevChar = null;
|
323 | var hasLineBreak = false;
|
324 | var hasFoldableLine = false;
|
325 | var shouldTrackWidth = lineWidth !== -1;
|
326 | var previousLineBreak = -1;
|
327 | var plain = isPlainSafeFirst(codePointAt(string, 0))
|
328 | && isPlainSafeLast(codePointAt(string, string.length - 1));
|
329 |
|
330 | if (singleLineOnly || forceQuotes) {
|
331 |
|
332 |
|
333 | for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
|
334 | char = codePointAt(string, i);
|
335 | if (!isPrintable(char)) {
|
336 | return STYLE_DOUBLE;
|
337 | }
|
338 | plain = plain && isPlainSafe(char, prevChar, inblock);
|
339 | prevChar = char;
|
340 | }
|
341 | } else {
|
342 |
|
343 | for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
|
344 | char = codePointAt(string, i);
|
345 | if (char === CHAR_LINE_FEED) {
|
346 | hasLineBreak = true;
|
347 |
|
348 | if (shouldTrackWidth) {
|
349 | hasFoldableLine = hasFoldableLine ||
|
350 |
|
351 | (i - previousLineBreak - 1 > lineWidth &&
|
352 | string[previousLineBreak + 1] !== ' ');
|
353 | previousLineBreak = i;
|
354 | }
|
355 | } else if (!isPrintable(char)) {
|
356 | return STYLE_DOUBLE;
|
357 | }
|
358 | plain = plain && isPlainSafe(char, prevChar, inblock);
|
359 | prevChar = char;
|
360 | }
|
361 |
|
362 | hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
|
363 | (i - previousLineBreak - 1 > lineWidth &&
|
364 | string[previousLineBreak + 1] !== ' '));
|
365 | }
|
366 |
|
367 |
|
368 |
|
369 | if (!hasLineBreak && !hasFoldableLine) {
|
370 |
|
371 |
|
372 | if (plain && !forceQuotes && !testAmbiguousType(string)) {
|
373 | return STYLE_PLAIN;
|
374 | }
|
375 | return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
|
376 | }
|
377 |
|
378 | if (indentPerLevel > 9 && needIndentIndicator(string)) {
|
379 | return STYLE_DOUBLE;
|
380 | }
|
381 |
|
382 |
|
383 | if (!forceQuotes) {
|
384 | return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
|
385 | }
|
386 | return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
|
387 | }
|
388 |
|
389 |
|
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 | function writeScalar(state, string, level, iskey, inblock) {
|
396 | state.dump = (function () {
|
397 | if (string.length === 0) {
|
398 | return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
|
399 | }
|
400 | if (!state.noCompatMode) {
|
401 | if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
|
402 | return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'");
|
403 | }
|
404 | }
|
405 |
|
406 | var indent = state.indent * Math.max(1, level);
|
407 |
|
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 | var lineWidth = state.lineWidth === -1
|
415 | ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
|
416 |
|
417 |
|
418 | var singleLineOnly = iskey
|
419 |
|
420 | || (state.flowLevel > -1 && level >= state.flowLevel);
|
421 | function testAmbiguity(string) {
|
422 | return testImplicitResolving(state, string);
|
423 | }
|
424 |
|
425 | switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,
|
426 | testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {
|
427 |
|
428 | case STYLE_PLAIN:
|
429 | return string;
|
430 | case STYLE_SINGLE:
|
431 | return "'" + string.replace(/'/g, "''") + "'";
|
432 | case STYLE_LITERAL:
|
433 | return '|' + blockHeader(string, state.indent)
|
434 | + dropEndingNewline(indentString(string, indent));
|
435 | case STYLE_FOLDED:
|
436 | return '>' + blockHeader(string, state.indent)
|
437 | + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
|
438 | case STYLE_DOUBLE:
|
439 | return '"' + escapeString(string, lineWidth) + '"';
|
440 | default:
|
441 | throw new YAMLException('impossible error: invalid scalar style');
|
442 | }
|
443 | }());
|
444 | }
|
445 |
|
446 |
|
447 | function blockHeader(string, indentPerLevel) {
|
448 | var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';
|
449 |
|
450 |
|
451 | var clip = string[string.length - 1] === '\n';
|
452 | var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
|
453 | var chomp = keep ? '+' : (clip ? '' : '-');
|
454 |
|
455 | return indentIndicator + chomp + '\n';
|
456 | }
|
457 |
|
458 |
|
459 | function dropEndingNewline(string) {
|
460 | return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
|
461 | }
|
462 |
|
463 |
|
464 |
|
465 | function foldString(string, width) {
|
466 |
|
467 |
|
468 |
|
469 |
|
470 | var lineRe = /(\n+)([^\n]*)/g;
|
471 |
|
472 |
|
473 | var result = (function () {
|
474 | var nextLF = string.indexOf('\n');
|
475 | nextLF = nextLF !== -1 ? nextLF : string.length;
|
476 | lineRe.lastIndex = nextLF;
|
477 | return foldLine(string.slice(0, nextLF), width);
|
478 | }());
|
479 |
|
480 | var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
|
481 | var moreIndented;
|
482 |
|
483 |
|
484 | var match;
|
485 | while ((match = lineRe.exec(string))) {
|
486 | var prefix = match[1], line = match[2];
|
487 | moreIndented = (line[0] === ' ');
|
488 | result += prefix
|
489 | + (!prevMoreIndented && !moreIndented && line !== ''
|
490 | ? '\n' : '')
|
491 | + foldLine(line, width);
|
492 | prevMoreIndented = moreIndented;
|
493 | }
|
494 |
|
495 | return result;
|
496 | }
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 | function foldLine(line, width) {
|
503 | if (line === '' || line[0] === ' ') return line;
|
504 |
|
505 |
|
506 | var breakRe = / [^ ]/g;
|
507 | var match;
|
508 |
|
509 | var start = 0, end, curr = 0, next = 0;
|
510 | var result = '';
|
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 | while ((match = breakRe.exec(line))) {
|
517 | next = match.index;
|
518 |
|
519 | if (next - start > width) {
|
520 | end = (curr > start) ? curr : next;
|
521 | result += '\n' + line.slice(start, end);
|
522 |
|
523 | start = end + 1;
|
524 | }
|
525 | curr = next;
|
526 | }
|
527 |
|
528 |
|
529 |
|
530 | result += '\n';
|
531 |
|
532 | if (line.length - start > width && curr > start) {
|
533 | result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
|
534 | } else {
|
535 | result += line.slice(start);
|
536 | }
|
537 |
|
538 | return result.slice(1);
|
539 | }
|
540 |
|
541 |
|
542 | function escapeString(string) {
|
543 | var result = '';
|
544 | var char = 0;
|
545 | var escapeSeq;
|
546 |
|
547 | for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
|
548 | char = codePointAt(string, i);
|
549 | escapeSeq = ESCAPE_SEQUENCES[char];
|
550 |
|
551 | if (!escapeSeq && isPrintable(char)) {
|
552 | result += string[i];
|
553 | if (char >= 0x10000) result += string[i + 1];
|
554 | } else {
|
555 | result += escapeSeq || encodeHex(char);
|
556 | }
|
557 | }
|
558 |
|
559 | return result;
|
560 | }
|
561 |
|
562 | function writeFlowSequence(state, level, object) {
|
563 | var _result = '',
|
564 | _tag = state.tag,
|
565 | index,
|
566 | length,
|
567 | value;
|
568 |
|
569 | for (index = 0, length = object.length; index < length; index += 1) {
|
570 | value = object[index];
|
571 |
|
572 | if (state.replacer) {
|
573 | value = state.replacer.call(object, String(index), value);
|
574 | }
|
575 |
|
576 |
|
577 | if (writeNode(state, level, value, false, false) ||
|
578 | (typeof value === 'undefined' &&
|
579 | writeNode(state, level, null, false, false))) {
|
580 |
|
581 | if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '');
|
582 | _result += state.dump;
|
583 | }
|
584 | }
|
585 |
|
586 | state.tag = _tag;
|
587 | state.dump = '[' + _result + ']';
|
588 | }
|
589 |
|
590 | function writeBlockSequence(state, level, object, compact) {
|
591 | var _result = '',
|
592 | _tag = state.tag,
|
593 | index,
|
594 | length,
|
595 | value;
|
596 |
|
597 | for (index = 0, length = object.length; index < length; index += 1) {
|
598 | value = object[index];
|
599 |
|
600 | if (state.replacer) {
|
601 | value = state.replacer.call(object, String(index), value);
|
602 | }
|
603 |
|
604 |
|
605 | if (writeNode(state, level + 1, value, true, true, false, true) ||
|
606 | (typeof value === 'undefined' &&
|
607 | writeNode(state, level + 1, null, true, true, false, true))) {
|
608 |
|
609 | if (!compact || _result !== '') {
|
610 | _result += generateNextLine(state, level);
|
611 | }
|
612 |
|
613 | if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
614 | _result += '-';
|
615 | } else {
|
616 | _result += '- ';
|
617 | }
|
618 |
|
619 | _result += state.dump;
|
620 | }
|
621 | }
|
622 |
|
623 | state.tag = _tag;
|
624 | state.dump = _result || '[]';
|
625 | }
|
626 |
|
627 | function writeFlowMapping(state, level, object) {
|
628 | var _result = '',
|
629 | _tag = state.tag,
|
630 | objectKeyList = Object.keys(object),
|
631 | index,
|
632 | length,
|
633 | objectKey,
|
634 | objectValue,
|
635 | pairBuffer;
|
636 |
|
637 | for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
638 |
|
639 | pairBuffer = '';
|
640 | if (_result !== '') pairBuffer += ', ';
|
641 |
|
642 | if (state.condenseFlow) pairBuffer += '"';
|
643 |
|
644 | objectKey = objectKeyList[index];
|
645 | objectValue = object[objectKey];
|
646 |
|
647 | if (state.replacer) {
|
648 | objectValue = state.replacer.call(object, objectKey, objectValue);
|
649 | }
|
650 |
|
651 | if (!writeNode(state, level, objectKey, false, false)) {
|
652 | continue;
|
653 | }
|
654 |
|
655 | if (state.dump.length > 1024) pairBuffer += '? ';
|
656 |
|
657 | pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');
|
658 |
|
659 | if (!writeNode(state, level, objectValue, false, false)) {
|
660 | continue;
|
661 | }
|
662 |
|
663 | pairBuffer += state.dump;
|
664 |
|
665 |
|
666 | _result += pairBuffer;
|
667 | }
|
668 |
|
669 | state.tag = _tag;
|
670 | state.dump = '{' + _result + '}';
|
671 | }
|
672 |
|
673 | function writeBlockMapping(state, level, object, compact) {
|
674 | var _result = '',
|
675 | _tag = state.tag,
|
676 | objectKeyList = Object.keys(object),
|
677 | index,
|
678 | length,
|
679 | objectKey,
|
680 | objectValue,
|
681 | explicitPair,
|
682 | pairBuffer;
|
683 |
|
684 |
|
685 | if (state.sortKeys === true) {
|
686 |
|
687 | objectKeyList.sort();
|
688 | } else if (typeof state.sortKeys === 'function') {
|
689 |
|
690 | objectKeyList.sort(state.sortKeys);
|
691 | } else if (state.sortKeys) {
|
692 |
|
693 | throw new YAMLException('sortKeys must be a boolean or a function');
|
694 | }
|
695 |
|
696 | for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
697 | pairBuffer = '';
|
698 |
|
699 | if (!compact || _result !== '') {
|
700 | pairBuffer += generateNextLine(state, level);
|
701 | }
|
702 |
|
703 | objectKey = objectKeyList[index];
|
704 | objectValue = object[objectKey];
|
705 |
|
706 | if (state.replacer) {
|
707 | objectValue = state.replacer.call(object, objectKey, objectValue);
|
708 | }
|
709 |
|
710 | if (!writeNode(state, level + 1, objectKey, true, true, true)) {
|
711 | continue;
|
712 | }
|
713 |
|
714 | explicitPair = (state.tag !== null && state.tag !== '?') ||
|
715 | (state.dump && state.dump.length > 1024);
|
716 |
|
717 | if (explicitPair) {
|
718 | if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
719 | pairBuffer += '?';
|
720 | } else {
|
721 | pairBuffer += '? ';
|
722 | }
|
723 | }
|
724 |
|
725 | pairBuffer += state.dump;
|
726 |
|
727 | if (explicitPair) {
|
728 | pairBuffer += generateNextLine(state, level);
|
729 | }
|
730 |
|
731 | if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
|
732 | continue;
|
733 | }
|
734 |
|
735 | if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
|
736 | pairBuffer += ':';
|
737 | } else {
|
738 | pairBuffer += ': ';
|
739 | }
|
740 |
|
741 | pairBuffer += state.dump;
|
742 |
|
743 |
|
744 | _result += pairBuffer;
|
745 | }
|
746 |
|
747 | state.tag = _tag;
|
748 | state.dump = _result || '{}';
|
749 | }
|
750 |
|
751 | function detectType(state, object, explicit) {
|
752 | var _result, typeList, index, length, type, style;
|
753 |
|
754 | typeList = explicit ? state.explicitTypes : state.implicitTypes;
|
755 |
|
756 | for (index = 0, length = typeList.length; index < length; index += 1) {
|
757 | type = typeList[index];
|
758 |
|
759 | if ((type.instanceOf || type.predicate) &&
|
760 | (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
|
761 | (!type.predicate || type.predicate(object))) {
|
762 |
|
763 | if (explicit) {
|
764 | if (type.multi && type.representName) {
|
765 | state.tag = type.representName(object);
|
766 | } else {
|
767 | state.tag = type.tag;
|
768 | }
|
769 | } else {
|
770 | state.tag = '?';
|
771 | }
|
772 |
|
773 | if (type.represent) {
|
774 | style = state.styleMap[type.tag] || type.defaultStyle;
|
775 |
|
776 | if (_toString.call(type.represent) === '[object Function]') {
|
777 | _result = type.represent(object, style);
|
778 | } else if (_hasOwnProperty.call(type.represent, style)) {
|
779 | _result = type.represent[style](object, style);
|
780 | } else {
|
781 | throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
|
782 | }
|
783 |
|
784 | state.dump = _result;
|
785 | }
|
786 |
|
787 | return true;
|
788 | }
|
789 | }
|
790 |
|
791 | return false;
|
792 | }
|
793 |
|
794 |
|
795 |
|
796 |
|
797 | function writeNode(state, level, object, block, compact, iskey, isblockseq) {
|
798 | state.tag = null;
|
799 | state.dump = object;
|
800 |
|
801 | if (!detectType(state, object, false)) {
|
802 | detectType(state, object, true);
|
803 | }
|
804 |
|
805 | var type = _toString.call(state.dump);
|
806 | var inblock = block;
|
807 | var tagStr;
|
808 |
|
809 | if (block) {
|
810 | block = (state.flowLevel < 0 || state.flowLevel > level);
|
811 | }
|
812 |
|
813 | var objectOrArray = type === '[object Object]' || type === '[object Array]',
|
814 | duplicateIndex,
|
815 | duplicate;
|
816 |
|
817 | if (objectOrArray) {
|
818 | duplicateIndex = state.duplicates.indexOf(object);
|
819 | duplicate = duplicateIndex !== -1;
|
820 | }
|
821 |
|
822 | if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
|
823 | compact = false;
|
824 | }
|
825 |
|
826 | if (duplicate && state.usedDuplicates[duplicateIndex]) {
|
827 | state.dump = '*ref_' + duplicateIndex;
|
828 | } else {
|
829 | if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
|
830 | state.usedDuplicates[duplicateIndex] = true;
|
831 | }
|
832 | if (type === '[object Object]') {
|
833 | if (block && (Object.keys(state.dump).length !== 0)) {
|
834 | writeBlockMapping(state, level, state.dump, compact);
|
835 | if (duplicate) {
|
836 | state.dump = '&ref_' + duplicateIndex + state.dump;
|
837 | }
|
838 | } else {
|
839 | writeFlowMapping(state, level, state.dump);
|
840 | if (duplicate) {
|
841 | state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
|
842 | }
|
843 | }
|
844 | } else if (type === '[object Array]') {
|
845 | if (block && (state.dump.length !== 0)) {
|
846 | if (state.noArrayIndent && !isblockseq && level > 0) {
|
847 | writeBlockSequence(state, level - 1, state.dump, compact);
|
848 | } else {
|
849 | writeBlockSequence(state, level, state.dump, compact);
|
850 | }
|
851 | if (duplicate) {
|
852 | state.dump = '&ref_' + duplicateIndex + state.dump;
|
853 | }
|
854 | } else {
|
855 | writeFlowSequence(state, level, state.dump);
|
856 | if (duplicate) {
|
857 | state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
|
858 | }
|
859 | }
|
860 | } else if (type === '[object String]') {
|
861 | if (state.tag !== '?') {
|
862 | writeScalar(state, state.dump, level, iskey, inblock);
|
863 | }
|
864 | } else if (type === '[object Undefined]') {
|
865 | return false;
|
866 | } else {
|
867 | if (state.skipInvalid) return false;
|
868 | throw new YAMLException('unacceptable kind of an object to dump ' + type);
|
869 | }
|
870 |
|
871 | if (state.tag !== null && state.tag !== '?') {
|
872 |
|
873 |
|
874 |
|
875 |
|
876 |
|
877 |
|
878 |
|
879 |
|
880 |
|
881 |
|
882 |
|
883 |
|
884 |
|
885 | tagStr = encodeURI(
|
886 | state.tag[0] === '!' ? state.tag.slice(1) : state.tag
|
887 | ).replace(/!/g, '%21');
|
888 |
|
889 | if (state.tag[0] === '!') {
|
890 | tagStr = '!' + tagStr;
|
891 | } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {
|
892 | tagStr = '!!' + tagStr.slice(18);
|
893 | } else {
|
894 | tagStr = '!<' + tagStr + '>';
|
895 | }
|
896 |
|
897 | state.dump = tagStr + ' ' + state.dump;
|
898 | }
|
899 | }
|
900 |
|
901 | return true;
|
902 | }
|
903 |
|
904 | function getDuplicateReferences(object, state) {
|
905 | var objects = [],
|
906 | duplicatesIndexes = [],
|
907 | index,
|
908 | length;
|
909 |
|
910 | inspectNode(object, objects, duplicatesIndexes);
|
911 |
|
912 | for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
|
913 | state.duplicates.push(objects[duplicatesIndexes[index]]);
|
914 | }
|
915 | state.usedDuplicates = new Array(length);
|
916 | }
|
917 |
|
918 | function inspectNode(object, objects, duplicatesIndexes) {
|
919 | var objectKeyList,
|
920 | index,
|
921 | length;
|
922 |
|
923 | if (object !== null && typeof object === 'object') {
|
924 | index = objects.indexOf(object);
|
925 | if (index !== -1) {
|
926 | if (duplicatesIndexes.indexOf(index) === -1) {
|
927 | duplicatesIndexes.push(index);
|
928 | }
|
929 | } else {
|
930 | objects.push(object);
|
931 |
|
932 | if (Array.isArray(object)) {
|
933 | for (index = 0, length = object.length; index < length; index += 1) {
|
934 | inspectNode(object[index], objects, duplicatesIndexes);
|
935 | }
|
936 | } else {
|
937 | objectKeyList = Object.keys(object);
|
938 |
|
939 | for (index = 0, length = objectKeyList.length; index < length; index += 1) {
|
940 | inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
|
941 | }
|
942 | }
|
943 | }
|
944 | }
|
945 | }
|
946 |
|
947 | function dump(input, options) {
|
948 | options = options || {};
|
949 |
|
950 | var state = new State(options);
|
951 |
|
952 | if (!state.noRefs) getDuplicateReferences(input, state);
|
953 |
|
954 | var value = input;
|
955 |
|
956 | if (state.replacer) {
|
957 | value = state.replacer.call({ '': value }, '', value);
|
958 | }
|
959 |
|
960 | if (writeNode(state, 0, value, true, true)) return state.dump + '\n';
|
961 |
|
962 | return '';
|
963 | }
|
964 |
|
965 | module.exports.dump = dump;
|