UNPKG

3.45 kBJavaScriptView Raw
1'use strict';
2
3var identity = require('../nodes/identity.js');
4var Scalar = require('../nodes/Scalar.js');
5var resolveBlockScalar = require('./resolve-block-scalar.js');
6var resolveFlowScalar = require('./resolve-flow-scalar.js');
7
8function composeScalar(ctx, token, tagToken, onError) {
9 const { value, type, comment, range } = token.type === 'block-scalar'
10 ? resolveBlockScalar.resolveBlockScalar(ctx, token, onError)
11 : resolveFlowScalar.resolveFlowScalar(token, ctx.options.strict, onError);
12 const tagName = tagToken
13 ? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg))
14 : null;
15 let tag;
16 if (ctx.options.stringKeys && ctx.atKey) {
17 tag = ctx.schema[identity.SCALAR];
18 }
19 else if (tagName)
20 tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
21 else if (token.type === 'scalar')
22 tag = findScalarTagByTest(ctx, value, token, onError);
23 else
24 tag = ctx.schema[identity.SCALAR];
25 let scalar;
26 try {
27 const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options);
28 scalar = identity.isScalar(res) ? res : new Scalar.Scalar(res);
29 }
30 catch (error) {
31 const msg = error instanceof Error ? error.message : String(error);
32 onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg);
33 scalar = new Scalar.Scalar(value);
34 }
35 scalar.range = range;
36 scalar.source = value;
37 if (type)
38 scalar.type = type;
39 if (tagName)
40 scalar.tag = tagName;
41 if (tag.format)
42 scalar.format = tag.format;
43 if (comment)
44 scalar.comment = comment;
45 return scalar;
46}
47function findScalarTagByName(schema, value, tagName, tagToken, onError) {
48 if (tagName === '!')
49 return schema[identity.SCALAR]; // non-specific tag
50 const matchWithTest = [];
51 for (const tag of schema.tags) {
52 if (!tag.collection && tag.tag === tagName) {
53 if (tag.default && tag.test)
54 matchWithTest.push(tag);
55 else
56 return tag;
57 }
58 }
59 for (const tag of matchWithTest)
60 if (tag.test?.test(value))
61 return tag;
62 const kt = schema.knownTags[tagName];
63 if (kt && !kt.collection) {
64 // Ensure that the known tag is available for stringifying,
65 // but does not get used by default.
66 schema.tags.push(Object.assign({}, kt, { default: false, test: undefined }));
67 return kt;
68 }
69 onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str');
70 return schema[identity.SCALAR];
71}
72function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
73 const tag = schema.tags.find(tag => (tag.default === true || (atKey && tag.default === 'key')) &&
74 tag.test?.test(value)) || schema[identity.SCALAR];
75 if (schema.compat) {
76 const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ??
77 schema[identity.SCALAR];
78 if (tag.tag !== compat.tag) {
79 const ts = directives.tagString(tag.tag);
80 const cs = directives.tagString(compat.tag);
81 const msg = `Value may be parsed as either ${ts} or ${cs}`;
82 onError(token, 'TAG_RESOLVE_FAILED', msg, true);
83 }
84 }
85 return tag;
86}
87
88exports.composeScalar = composeScalar;