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