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.
80 lines
3.1 KiB
80 lines
3.1 KiB
import { SCALAR, isScalar } from '../nodes/Node.js'; |
|
import { Scalar } from '../nodes/Scalar.js'; |
|
import { resolveBlockScalar } from './resolve-block-scalar.js'; |
|
import { resolveFlowScalar } from './resolve-flow-scalar.js'; |
|
|
|
function composeScalar(ctx, token, tagToken, onError) { |
|
const { value, type, comment, range } = token.type === 'block-scalar' |
|
? resolveBlockScalar(token, ctx.options.strict, onError) |
|
: resolveFlowScalar(token, ctx.options.strict, onError); |
|
const tagName = tagToken |
|
? ctx.directives.tagName(tagToken.source, msg => onError(tagToken, 'TAG_RESOLVE_FAILED', msg)) |
|
: null; |
|
const tag = tagToken && tagName |
|
? findScalarTagByName(ctx.schema, value, tagName, tagToken, onError) |
|
: token.type === 'scalar' |
|
? findScalarTagByTest(ctx, value, token, onError) |
|
: ctx.schema[SCALAR]; |
|
let scalar; |
|
try { |
|
const res = tag.resolve(value, msg => onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg), ctx.options); |
|
scalar = isScalar(res) ? res : new Scalar(res); |
|
} |
|
catch (error) { |
|
const msg = error instanceof Error ? error.message : String(error); |
|
onError(tagToken ?? token, 'TAG_RESOLVE_FAILED', msg); |
|
scalar = new Scalar(value); |
|
} |
|
scalar.range = range; |
|
scalar.source = value; |
|
if (type) |
|
scalar.type = type; |
|
if (tagName) |
|
scalar.tag = tagName; |
|
if (tag.format) |
|
scalar.format = tag.format; |
|
if (comment) |
|
scalar.comment = comment; |
|
return scalar; |
|
} |
|
function findScalarTagByName(schema, value, tagName, tagToken, onError) { |
|
if (tagName === '!') |
|
return schema[SCALAR]; // non-specific tag |
|
const matchWithTest = []; |
|
for (const tag of schema.tags) { |
|
if (!tag.collection && tag.tag === tagName) { |
|
if (tag.default && tag.test) |
|
matchWithTest.push(tag); |
|
else |
|
return tag; |
|
} |
|
} |
|
for (const tag of matchWithTest) |
|
if (tag.test?.test(value)) |
|
return tag; |
|
const kt = schema.knownTags[tagName]; |
|
if (kt && !kt.collection) { |
|
// Ensure that the known tag is available for stringifying, |
|
// but does not get used by default. |
|
schema.tags.push(Object.assign({}, kt, { default: false, test: undefined })); |
|
return kt; |
|
} |
|
onError(tagToken, 'TAG_RESOLVE_FAILED', `Unresolved tag: ${tagName}`, tagName !== 'tag:yaml.org,2002:str'); |
|
return schema[SCALAR]; |
|
} |
|
function findScalarTagByTest({ directives, schema }, value, token, onError) { |
|
const tag = schema.tags.find(tag => tag.default && tag.test?.test(value)) || schema[SCALAR]; |
|
if (schema.compat) { |
|
const compat = schema.compat.find(tag => tag.default && tag.test?.test(value)) ?? |
|
schema[SCALAR]; |
|
if (tag.tag !== compat.tag) { |
|
const ts = directives.tagString(tag.tag); |
|
const cs = directives.tagString(compat.tag); |
|
const msg = `Value may be parsed as either ${ts} or ${cs}`; |
|
onError(token, 'TAG_RESOLVE_FAILED', msg, true); |
|
} |
|
} |
|
return tag; |
|
} |
|
|
|
export { composeScalar };
|
|
|