deno.land / std@0.224.0 / front_matter / create_extractor.ts

create_extractor.ts
View Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
import { EXTRACT_REGEXP_MAP, RECOGNIZE_REGEXP_MAP } from "./_formats.ts";
type Format = "yaml" | "toml" | "json" | "unknown";
/** Return type for {@linkcode Extractor}. */export type Extract<T> = { frontMatter: string; body: string; attrs: T;};
/** Function return type for {@linkcode createExtractor}. */export type Extractor = <T = Record<string, unknown>>( str: string,) => Extract<T>;
/** Parser function type used alongside {@linkcode createExtractor}. */export type Parser = <T = Record<string, unknown>>(str: string) => T;
function _extract<T>( str: string, rx: RegExp, parse: Parser,): Extract<T> { const match = rx.exec(str); if (!match || match.index !== 0) { throw new TypeError("Unexpected end of input"); } const frontMatter = match.at(-1)?.replace(/^\s+|\s+$/g, "") || ""; const attrs = parse(frontMatter) as T; const body = str.replace(match[0], ""); return { frontMatter, body, attrs };}
/** * Recognizes the format of the front matter in a string. Supports YAML, TOML and JSON. * * @param str String to recognize. * @param formats A list of formats to recognize. Defaults to all supported formats. * * ```ts * import { recognize } from "https://deno.land/std@$STD_VERSION/front_matter/mod.ts"; * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts"; * * assertEquals(recognize("---\ntitle: Three dashes marks the spot\n---\n"), "yaml"); * assertEquals(recognize("---toml\ntitle = 'Three dashes followed by format marks the spot'\n---\n"), "toml"); * assertEquals(recognize("---json\n{\"title\": \"Three dashes followed by format marks the spot\"}\n---\n"), "json"); * assertEquals(recognize("---xml\n<title>Three dashes marks the spot</title>\n---\n"), "unknown"); * * assertEquals(recognize("---json\n<title>Three dashes marks the spot</title>\n---\n", ["yaml"]), "unknown"); */function recognize(str: string, formats?: Format[]): Format { if (!formats) { formats = Object.keys(RECOGNIZE_REGEXP_MAP) as Format[]; }
const [firstLine] = str.split(/(\r?\n)/) as [string];
for (const format of formats) { if (format === "unknown") { continue; }
if (RECOGNIZE_REGEXP_MAP[format].test(firstLine)) { return format; } }
return "unknown";}
/** * Factory that creates a function that extracts front matter from a string with the given parsers. * Supports YAML, TOML and JSON. * * @param formats A descriptor containing Format-parser pairs to use for each format. * @returns A function that extracts front matter from a string with the given parsers. * * ```ts * import { createExtractor, Parser } from "https://deno.land/std@$STD_VERSION/front_matter/mod.ts"; * import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/assert_equals.ts"; * import { parse as parseYAML } from "https://deno.land/std@$STD_VERSION/yaml/parse.ts"; * import { parse as parseTOML } from "https://deno.land/std@$STD_VERSION/toml/parse.ts"; * const extractYAML = createExtractor({ yaml: parseYAML as Parser }); * const extractTOML = createExtractor({ toml: parseTOML as Parser }); * const extractJSON = createExtractor({ json: JSON.parse as Parser }); * const extractYAMLOrJSON = createExtractor({ * yaml: parseYAML as Parser, * json: JSON.parse as Parser, * }); * * let { attrs, body, frontMatter } = extractYAML<{ title: string }>("---\ntitle: Three dashes marks the spot\n---\nferret"); * assertEquals(attrs.title, "Three dashes marks the spot"); * assertEquals(body, "ferret"); * assertEquals(frontMatter, "title: Three dashes marks the spot"); * * ({ attrs, body, frontMatter } = extractTOML<{ title: string }>("---toml\ntitle = 'Three dashes followed by format marks the spot'\n---\n")); * assertEquals(attrs.title, "Three dashes followed by format marks the spot"); * assertEquals(body, ""); * assertEquals(frontMatter, "title = 'Three dashes followed by format marks the spot'"); * * ({ attrs, body, frontMatter } = extractJSON<{ title: string }>("---json\n{\"title\": \"Three dashes followed by format marks the spot\"}\n---\ngoat")); * assertEquals(attrs.title, "Three dashes followed by format marks the spot"); * assertEquals(body, "goat"); * assertEquals(frontMatter, "{\"title\": \"Three dashes followed by format marks the spot\"}"); * * ({ attrs, body, frontMatter } = extractYAMLOrJSON<{ title: string }>("---\ntitle: Three dashes marks the spot\n---\nferret")); * assertEquals(attrs.title, "Three dashes marks the spot"); * assertEquals(body, "ferret"); * assertEquals(frontMatter, "title: Three dashes marks the spot"); * * ({ attrs, body, frontMatter } = extractYAMLOrJSON<{ title: string }>("---json\n{\"title\": \"Three dashes followed by format marks the spot\"}\n---\ngoat")); * assertEquals(attrs.title, "Three dashes followed by format marks the spot"); * assertEquals(body, "goat"); * assertEquals(frontMatter, "{\"title\": \"Three dashes followed by format marks the spot\"}"); * ``` */export function createExtractor( formats: Partial<Record<"yaml" | "toml" | "json" | "unknown", Parser>>,): Extractor { const formatKeys = Object.keys(formats) as Format[];
return function extract<T>(str: string): Extract<T> { const format = recognize(str, formatKeys); const parser = formats[format];
if (format === "unknown" || !parser) { throw new TypeError(`Unsupported front matter format`); }
return _extract(str, EXTRACT_REGEXP_MAP[format], parser); };}
std

Version Info

Tagged at
6 months ago