2019-11-18 14:39:32 +00:00
|
|
|
// Ported from js-yaml v3.13.1:
|
|
|
|
// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
|
|
|
|
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
|
2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2023-03-18 12:36:00 +00:00
|
|
|
// This module is browser compatible.
|
2019-11-18 14:39:32 +00:00
|
|
|
|
2024-08-08 13:53:55 +00:00
|
|
|
import { isEOL } from "./_chars.ts";
|
|
|
|
import { LoaderState } from "./_loader_state.ts";
|
2024-07-24 06:26:56 +00:00
|
|
|
import { SCHEMA_MAP, type SchemaType } from "./_schema.ts";
|
|
|
|
|
|
|
|
export type { SchemaType };
|
2019-11-18 14:39:32 +00:00
|
|
|
|
2024-07-06 08:35:15 +00:00
|
|
|
/** Options for {@linkcode parse}. */
|
2024-06-25 01:17:26 +00:00
|
|
|
export interface ParseOptions {
|
2024-07-06 08:35:15 +00:00
|
|
|
/**
|
2024-07-24 06:26:56 +00:00
|
|
|
* Name of the schema to use.
|
2024-07-06 08:35:15 +00:00
|
|
|
*
|
|
|
|
* @default {"default"}
|
|
|
|
*/
|
2024-07-24 06:26:56 +00:00
|
|
|
schema?: SchemaType;
|
2024-07-06 08:35:15 +00:00
|
|
|
/**
|
|
|
|
* If `true`, duplicate keys will overwrite previous values. Otherwise,
|
2024-07-16 10:12:33 +00:00
|
|
|
* duplicate keys will throw a {@linkcode SyntaxError}.
|
2024-07-06 08:35:15 +00:00
|
|
|
*
|
|
|
|
* @default {false}
|
|
|
|
*/
|
2024-07-04 04:59:06 +00:00
|
|
|
allowDuplicateKeys?: boolean;
|
2024-07-06 08:35:15 +00:00
|
|
|
/**
|
|
|
|
* If defined, a function to call on warning messages taking an
|
|
|
|
* {@linkcode Error} as its only argument.
|
|
|
|
*/
|
2024-07-12 00:02:52 +00:00
|
|
|
onWarning?(error: Error): void;
|
2024-06-25 01:17:26 +00:00
|
|
|
}
|
2019-11-18 14:39:32 +00:00
|
|
|
|
2024-08-08 13:53:55 +00:00
|
|
|
function sanitizeInput(input: string) {
|
|
|
|
input = String(input);
|
|
|
|
|
|
|
|
if (input.length > 0) {
|
2024-08-27 14:51:27 +00:00
|
|
|
// Add trailing `\n` if not exists
|
2024-08-08 13:53:55 +00:00
|
|
|
if (!isEOL(input.charCodeAt(input.length - 1))) input += "\n";
|
|
|
|
|
|
|
|
// Strip BOM
|
|
|
|
if (input.charCodeAt(0) === 0xfeff) input = input.slice(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use 0 as string terminator. That significantly simplifies bounds check.
|
|
|
|
input += "\0";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2019-11-18 14:39:32 +00:00
|
|
|
/**
|
2024-07-06 08:35:15 +00:00
|
|
|
* Parse and return a YAML string as a parsed YAML document object.
|
2019-11-18 14:39:32 +00:00
|
|
|
*
|
2024-07-06 08:35:15 +00:00
|
|
|
* Note: This does not support functions. Untrusted data is safe to parse.
|
2024-06-25 06:01:58 +00:00
|
|
|
*
|
|
|
|
* @example Usage
|
|
|
|
* ```ts
|
|
|
|
* import { parse } from "@std/yaml/parse";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2024-06-25 06:01:58 +00:00
|
|
|
*
|
|
|
|
* const data = parse(`
|
|
|
|
* id: 1
|
|
|
|
* name: Alice
|
|
|
|
* `);
|
|
|
|
*
|
|
|
|
* assertEquals(data, { id: 1, name: "Alice" });
|
|
|
|
* ```
|
|
|
|
*
|
2024-07-16 10:12:33 +00:00
|
|
|
* @throws {SyntaxError} Throws error on invalid YAML.
|
2024-06-25 06:01:58 +00:00
|
|
|
* @param content YAML string to parse.
|
|
|
|
* @param options Parsing options.
|
|
|
|
* @returns Parsed document.
|
2019-11-18 14:39:32 +00:00
|
|
|
*/
|
2024-07-01 22:42:32 +00:00
|
|
|
export function parse(
|
|
|
|
content: string,
|
|
|
|
options: ParseOptions = {},
|
|
|
|
): unknown {
|
2024-08-08 13:53:55 +00:00
|
|
|
content = sanitizeInput(content);
|
|
|
|
const state = new LoaderState(content, {
|
|
|
|
...options,
|
refactor(archive,async,cli,csv,dotenv,encoding,expect,fmt,front-matter,fs,http,internal,log,net,path,semver,testing,text,webgpu,yaml): enable `"exactOptionalPropertyTypes"` option (#5892)
2024-09-04 05:15:01 +00:00
|
|
|
schema: SCHEMA_MAP.get(options.schema!)!,
|
2024-08-08 13:53:55 +00:00
|
|
|
});
|
|
|
|
const documentGenerator = state.readDocuments();
|
|
|
|
const document = documentGenerator.next().value;
|
|
|
|
if (!documentGenerator.next().done) {
|
|
|
|
throw new SyntaxError(
|
2024-08-27 05:03:26 +00:00
|
|
|
"Found more than 1 document in the stream: expected a single document",
|
2024-08-08 13:53:55 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return document ?? null;
|
2019-11-18 14:39:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 06:01:58 +00:00
|
|
|
/**
|
2024-07-06 08:35:15 +00:00
|
|
|
* Same as {@linkcode parse}, but understands multi-document YAML sources, and
|
|
|
|
* returns multiple parsed YAML document objects.
|
2024-06-25 06:01:58 +00:00
|
|
|
*
|
|
|
|
* @example Usage
|
|
|
|
* ```ts
|
|
|
|
* import { parseAll } from "@std/yaml/parse";
|
refactor(assert,async,bytes,cli,collections,crypto,csv,data-structures,datetime,dotenv,encoding,expect,fmt,front-matter,fs,html,http,ini,internal,io,json,jsonc,log,media-types,msgpack,net,path,semver,streams,testing,text,toml,ulid,url,uuid,webgpu,yaml): import from `@std/assert` (#5199)
* refactor: import from `@std/assert`
* update
2024-06-30 08:30:10 +00:00
|
|
|
* import { assertEquals } from "@std/assert";
|
2024-06-25 06:01:58 +00:00
|
|
|
*
|
|
|
|
* const data = parseAll(`
|
|
|
|
* ---
|
|
|
|
* id: 1
|
|
|
|
* name: Alice
|
|
|
|
* ---
|
|
|
|
* id: 2
|
|
|
|
* name: Bob
|
|
|
|
* ---
|
|
|
|
* id: 3
|
|
|
|
* name: Eve
|
|
|
|
* `);
|
|
|
|
* assertEquals(data, [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Eve" }]);
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* @param content YAML string to parse.
|
|
|
|
* @param options Parsing options.
|
|
|
|
* @returns Array of parsed documents.
|
|
|
|
*/
|
2024-07-01 22:42:32 +00:00
|
|
|
export function parseAll(content: string, options: ParseOptions = {}): unknown {
|
2024-08-08 13:53:55 +00:00
|
|
|
content = sanitizeInput(content);
|
|
|
|
const state = new LoaderState(content, {
|
2024-07-01 22:42:32 +00:00
|
|
|
...options,
|
refactor(archive,async,cli,csv,dotenv,encoding,expect,fmt,front-matter,fs,http,internal,log,net,path,semver,testing,text,webgpu,yaml): enable `"exactOptionalPropertyTypes"` option (#5892)
2024-09-04 05:15:01 +00:00
|
|
|
schema: SCHEMA_MAP.get(options.schema!)!,
|
2024-07-01 22:42:32 +00:00
|
|
|
});
|
2024-08-08 13:53:55 +00:00
|
|
|
return [...state.readDocuments()];
|
2019-11-18 14:39:32 +00:00
|
|
|
}
|