You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.1 KiB
134 lines
4.1 KiB
'use strict'; |
|
|
|
var Node = require('./nodes/Node.js'); |
|
var publicApi = require('./public-api.js'); |
|
var visit = require('./visit.js'); |
|
|
|
const scalarChar = { |
|
BLOCK_FOLDED: '>', |
|
BLOCK_LITERAL: '|', |
|
PLAIN: ':', |
|
QUOTE_DOUBLE: '"', |
|
QUOTE_SINGLE: "'" |
|
}; |
|
function anchorExists(doc, anchor) { |
|
let found = false; |
|
visit.visit(doc, { |
|
Value(_key, node) { |
|
if (node.anchor === anchor) { |
|
found = true; |
|
return visit.visit.BREAK; |
|
} |
|
} |
|
}); |
|
return found; |
|
} |
|
// test harness for yaml-test-suite event tests |
|
function testEvents(src) { |
|
const docs = publicApi.parseAllDocuments(src); |
|
const errDoc = docs.find(doc => doc.errors.length > 0); |
|
const error = errDoc ? errDoc.errors[0].message : null; |
|
const events = ['+STR']; |
|
try { |
|
for (let i = 0; i < docs.length; ++i) { |
|
const doc = docs[i]; |
|
let root = doc.contents; |
|
if (Array.isArray(root)) |
|
root = root[0]; |
|
const [rootStart] = doc.range || [0]; |
|
const error = doc.errors[0]; |
|
if (error && (!error.pos || error.pos[0] < rootStart)) |
|
throw new Error(); |
|
let docStart = '+DOC'; |
|
if (doc.directives.docStart) |
|
docStart += ' ---'; |
|
else if (doc.contents && |
|
doc.contents.range[2] === doc.contents.range[0] && |
|
!doc.contents.anchor && |
|
!doc.contents.tag) |
|
continue; |
|
events.push(docStart); |
|
addEvents(events, doc, error?.pos[0] ?? -1, root); |
|
let docEnd = '-DOC'; |
|
if (doc.directives.docEnd) |
|
docEnd += ' ...'; |
|
events.push(docEnd); |
|
} |
|
} |
|
catch (e) { |
|
return { events, error: error ?? e }; |
|
} |
|
events.push('-STR'); |
|
return { events, error }; |
|
} |
|
function addEvents(events, doc, errPos, node) { |
|
if (!node) { |
|
events.push('=VAL :'); |
|
return; |
|
} |
|
if (errPos !== -1 && Node.isNode(node) && node.range[0] >= errPos) |
|
throw new Error(); |
|
let props = ''; |
|
let anchor = Node.isScalar(node) || Node.isCollection(node) ? node.anchor : undefined; |
|
if (anchor) { |
|
if (/\d$/.test(anchor)) { |
|
const alt = anchor.replace(/\d$/, ''); |
|
if (anchorExists(doc, alt)) |
|
anchor = alt; |
|
} |
|
props = ` &${anchor}`; |
|
} |
|
if (Node.isNode(node) && node.tag) |
|
props += ` <${node.tag}>`; |
|
if (Node.isMap(node)) { |
|
const ev = node.flow ? '+MAP {}' : '+MAP'; |
|
events.push(`${ev}${props}`); |
|
node.items.forEach(({ key, value }) => { |
|
addEvents(events, doc, errPos, key); |
|
addEvents(events, doc, errPos, value); |
|
}); |
|
events.push('-MAP'); |
|
} |
|
else if (Node.isSeq(node)) { |
|
const ev = node.flow ? '+SEQ []' : '+SEQ'; |
|
events.push(`${ev}${props}`); |
|
node.items.forEach(item => { |
|
addEvents(events, doc, errPos, item); |
|
}); |
|
events.push('-SEQ'); |
|
} |
|
else if (Node.isPair(node)) { |
|
events.push(`+MAP${props}`); |
|
addEvents(events, doc, errPos, node.key); |
|
addEvents(events, doc, errPos, node.value); |
|
events.push('-MAP'); |
|
} |
|
else if (Node.isAlias(node)) { |
|
let alias = node.source; |
|
if (alias && /\d$/.test(alias)) { |
|
const alt = alias.replace(/\d$/, ''); |
|
if (anchorExists(doc, alt)) |
|
alias = alt; |
|
} |
|
events.push(`=ALI${props} *${alias}`); |
|
} |
|
else { |
|
const scalar = scalarChar[String(node.type)]; |
|
if (!scalar) |
|
throw new Error(`Unexpected node type ${node.type}`); |
|
const value = node.source |
|
.replace(/\\/g, '\\\\') |
|
.replace(/\0/g, '\\0') |
|
.replace(/\x07/g, '\\a') |
|
.replace(/\x08/g, '\\b') |
|
.replace(/\t/g, '\\t') |
|
.replace(/\n/g, '\\n') |
|
.replace(/\v/g, '\\v') |
|
.replace(/\f/g, '\\f') |
|
.replace(/\r/g, '\\r') |
|
.replace(/\x1b/g, '\\e'); |
|
events.push(`=VAL${props} ${scalar}${value}`); |
|
} |
|
} |
|
|
|
exports.testEvents = testEvents;
|
|
|