[d24f17c] | 1 | 'use strict';
|
---|
| 2 |
|
---|
| 3 | var identity = require('./nodes/identity.js');
|
---|
| 4 | var publicApi = require('./public-api.js');
|
---|
| 5 | var visit = require('./visit.js');
|
---|
| 6 |
|
---|
| 7 | const scalarChar = {
|
---|
| 8 | BLOCK_FOLDED: '>',
|
---|
| 9 | BLOCK_LITERAL: '|',
|
---|
| 10 | PLAIN: ':',
|
---|
| 11 | QUOTE_DOUBLE: '"',
|
---|
| 12 | QUOTE_SINGLE: "'"
|
---|
| 13 | };
|
---|
| 14 | function anchorExists(doc, anchor) {
|
---|
| 15 | let found = false;
|
---|
| 16 | visit.visit(doc, {
|
---|
| 17 | Value(_key, node) {
|
---|
| 18 | if (node.anchor === anchor) {
|
---|
| 19 | found = true;
|
---|
| 20 | return visit.visit.BREAK;
|
---|
| 21 | }
|
---|
| 22 | }
|
---|
| 23 | });
|
---|
| 24 | return found;
|
---|
| 25 | }
|
---|
| 26 | // test harness for yaml-test-suite event tests
|
---|
| 27 | function testEvents(src) {
|
---|
| 28 | const docs = publicApi.parseAllDocuments(src);
|
---|
| 29 | const errDoc = docs.find(doc => doc.errors.length > 0);
|
---|
| 30 | const error = errDoc ? errDoc.errors[0].message : null;
|
---|
| 31 | const events = ['+STR'];
|
---|
| 32 | try {
|
---|
| 33 | for (let i = 0; i < docs.length; ++i) {
|
---|
| 34 | const doc = docs[i];
|
---|
| 35 | let root = doc.contents;
|
---|
| 36 | if (Array.isArray(root))
|
---|
| 37 | root = root[0];
|
---|
| 38 | const [rootStart] = doc.range || [0];
|
---|
| 39 | const error = doc.errors[0];
|
---|
| 40 | if (error && (!error.pos || error.pos[0] < rootStart))
|
---|
| 41 | throw new Error();
|
---|
| 42 | let docStart = '+DOC';
|
---|
| 43 | if (doc.directives.docStart)
|
---|
| 44 | docStart += ' ---';
|
---|
| 45 | else if (doc.contents &&
|
---|
| 46 | doc.contents.range[2] === doc.contents.range[0] &&
|
---|
| 47 | !doc.contents.anchor &&
|
---|
| 48 | !doc.contents.tag)
|
---|
| 49 | continue;
|
---|
| 50 | events.push(docStart);
|
---|
| 51 | addEvents(events, doc, error?.pos[0] ?? -1, root);
|
---|
| 52 | let docEnd = '-DOC';
|
---|
| 53 | if (doc.directives.docEnd)
|
---|
| 54 | docEnd += ' ...';
|
---|
| 55 | events.push(docEnd);
|
---|
| 56 | }
|
---|
| 57 | }
|
---|
| 58 | catch (e) {
|
---|
| 59 | return { events, error: error ?? e };
|
---|
| 60 | }
|
---|
| 61 | events.push('-STR');
|
---|
| 62 | return { events, error };
|
---|
| 63 | }
|
---|
| 64 | function addEvents(events, doc, errPos, node) {
|
---|
| 65 | if (!node) {
|
---|
| 66 | events.push('=VAL :');
|
---|
| 67 | return;
|
---|
| 68 | }
|
---|
| 69 | if (errPos !== -1 && identity.isNode(node) && node.range[0] >= errPos)
|
---|
| 70 | throw new Error();
|
---|
| 71 | let props = '';
|
---|
| 72 | let anchor = identity.isScalar(node) || identity.isCollection(node) ? node.anchor : undefined;
|
---|
| 73 | if (anchor) {
|
---|
| 74 | if (/\d$/.test(anchor)) {
|
---|
| 75 | const alt = anchor.replace(/\d$/, '');
|
---|
| 76 | if (anchorExists(doc, alt))
|
---|
| 77 | anchor = alt;
|
---|
| 78 | }
|
---|
| 79 | props = ` &${anchor}`;
|
---|
| 80 | }
|
---|
| 81 | if (identity.isNode(node) && node.tag)
|
---|
| 82 | props += ` <${node.tag}>`;
|
---|
| 83 | if (identity.isMap(node)) {
|
---|
| 84 | const ev = node.flow ? '+MAP {}' : '+MAP';
|
---|
| 85 | events.push(`${ev}${props}`);
|
---|
| 86 | node.items.forEach(({ key, value }) => {
|
---|
| 87 | addEvents(events, doc, errPos, key);
|
---|
| 88 | addEvents(events, doc, errPos, value);
|
---|
| 89 | });
|
---|
| 90 | events.push('-MAP');
|
---|
| 91 | }
|
---|
| 92 | else if (identity.isSeq(node)) {
|
---|
| 93 | const ev = node.flow ? '+SEQ []' : '+SEQ';
|
---|
| 94 | events.push(`${ev}${props}`);
|
---|
| 95 | node.items.forEach(item => {
|
---|
| 96 | addEvents(events, doc, errPos, item);
|
---|
| 97 | });
|
---|
| 98 | events.push('-SEQ');
|
---|
| 99 | }
|
---|
| 100 | else if (identity.isPair(node)) {
|
---|
| 101 | events.push(`+MAP${props}`);
|
---|
| 102 | addEvents(events, doc, errPos, node.key);
|
---|
| 103 | addEvents(events, doc, errPos, node.value);
|
---|
| 104 | events.push('-MAP');
|
---|
| 105 | }
|
---|
| 106 | else if (identity.isAlias(node)) {
|
---|
| 107 | let alias = node.source;
|
---|
| 108 | if (alias && /\d$/.test(alias)) {
|
---|
| 109 | const alt = alias.replace(/\d$/, '');
|
---|
| 110 | if (anchorExists(doc, alt))
|
---|
| 111 | alias = alt;
|
---|
| 112 | }
|
---|
| 113 | events.push(`=ALI${props} *${alias}`);
|
---|
| 114 | }
|
---|
| 115 | else {
|
---|
| 116 | const scalar = scalarChar[String(node.type)];
|
---|
| 117 | if (!scalar)
|
---|
| 118 | throw new Error(`Unexpected node type ${node.type}`);
|
---|
| 119 | const value = node.source
|
---|
| 120 | .replace(/\\/g, '\\\\')
|
---|
| 121 | .replace(/\0/g, '\\0')
|
---|
| 122 | .replace(/\x07/g, '\\a')
|
---|
| 123 | .replace(/\x08/g, '\\b')
|
---|
| 124 | .replace(/\t/g, '\\t')
|
---|
| 125 | .replace(/\n/g, '\\n')
|
---|
| 126 | .replace(/\v/g, '\\v')
|
---|
| 127 | .replace(/\f/g, '\\f')
|
---|
| 128 | .replace(/\r/g, '\\r')
|
---|
| 129 | .replace(/\x1b/g, '\\e');
|
---|
| 130 | events.push(`=VAL${props} ${scalar}${value}`);
|
---|
| 131 | }
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | exports.testEvents = testEvents;
|
---|