[d24f17c] | 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;
|
---|