gray-matter-es 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/defaults.mjs +19 -0
- package/dist/defaults.mjs.map +1 -0
- package/dist/engines.d.mts +8 -0
- package/dist/engines.mjs +63 -0
- package/dist/engines.mjs.map +1 -0
- package/dist/excerpt.mjs +26 -0
- package/dist/excerpt.mjs.map +1 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +126 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_chars.mjs +45 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_chars.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_dumper_state.mjs +437 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_dumper_state.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_loader_state.mjs +909 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_loader_state.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_schema.mjs +115 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_schema.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/binary.mjs +89 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/binary.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/bool.mjs +35 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/bool.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/float.mjs +55 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/float.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/int.mjs +114 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/int.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/map.mjs +15 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/map.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/merge.mjs +11 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/merge.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/nil.mjs +20 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/nil.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/omap.mjs +28 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/omap.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/pairs.mjs +19 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/pairs.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/regexp.mjs +26 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/regexp.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/seq.mjs +11 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/seq.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/set.mjs +14 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/set.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/str.mjs +11 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/str.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/timestamp.mjs +54 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/timestamp.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/undefined.mjs +19 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_type/undefined.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_utils.mjs +14 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_utils.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/mod.mjs +4 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/parse.mjs +50 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/parse.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/stringify.mjs +32 -0
- package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/stringify.mjs.map +1 -0
- package/dist/parse.mjs +13 -0
- package/dist/parse.mjs.map +1 -0
- package/dist/stringify.mjs +52 -0
- package/dist/stringify.mjs.map +1 -0
- package/dist/to-file.mjs +44 -0
- package/dist/to-file.mjs.map +1 -0
- package/dist/types.d.mts +85 -0
- package/dist/utils.mjs +60 -0
- package/dist/utils.mjs.map +1 -0
- package/package.json +61 -0
- package/src/defaults.ts +17 -0
- package/src/engines.ts +217 -0
- package/src/excerpt.ts +146 -0
- package/src/index.ts +481 -0
- package/src/parse.ts +9 -0
- package/src/stringify.ts +187 -0
- package/src/to-file.ts +178 -0
- package/src/types.ts +84 -0
- package/src/utils.ts +158 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ryoppippi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# gray-matter-es
|
|
2
|
+
|
|
3
|
+
ESM-only [gray-matter](https://github.com/jonschlinkert/gray-matter) implementation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 ESM-only, no CommonJS
|
|
8
|
+
- 📦 Zero runtime dependencies (YAML parser bundled from [@std/yaml](https://jsr.io/@std/yaml))
|
|
9
|
+
- 🔷 Full TypeScript support with strict types
|
|
10
|
+
- ✅ API compatible with gray-matter
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install gray-matter-es
|
|
16
|
+
# or
|
|
17
|
+
pnpm add gray-matter-es
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import matter from "gray-matter-es";
|
|
24
|
+
|
|
25
|
+
// Parse front matter
|
|
26
|
+
const file = matter("---\ntitle: Hello\n---\nThis is content");
|
|
27
|
+
console.log(file.data); // { title: 'Hello' }
|
|
28
|
+
console.log(file.content); // 'This is content'
|
|
29
|
+
|
|
30
|
+
// Stringify
|
|
31
|
+
const str = matter.stringify("content", { title: "Hello" });
|
|
32
|
+
// ---
|
|
33
|
+
// title: Hello
|
|
34
|
+
// ---
|
|
35
|
+
// content
|
|
36
|
+
|
|
37
|
+
// Read from file (Node.js)
|
|
38
|
+
const fileFromDisk = matter.read("./post.md");
|
|
39
|
+
|
|
40
|
+
// Test if string has front matter
|
|
41
|
+
matter.test("---\ntitle: Hello\n---"); // true
|
|
42
|
+
|
|
43
|
+
// Detect language
|
|
44
|
+
matter.language("---json\n{}\n---"); // { raw: 'json', name: 'json' }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Custom Delimiters
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
const file = matter("~~~\ntitle: Hello\n~~~\ncontent", {
|
|
51
|
+
delimiters: "~~~",
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### JSON Front Matter
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const file = matter('---json\n{"title": "Hello"}\n---\ncontent');
|
|
59
|
+
console.log(file.data); // { title: 'Hello' }
|
|
60
|
+
console.log(file.language); // 'json'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Excerpt
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const file = matter("---\ntitle: Hello\n---\nexcerpt\n---\ncontent", {
|
|
67
|
+
excerpt: true,
|
|
68
|
+
});
|
|
69
|
+
console.log(file.excerpt); // 'excerpt\n'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API
|
|
73
|
+
|
|
74
|
+
### `matter(input, options?)`
|
|
75
|
+
|
|
76
|
+
Parse front matter from a string or buffer.
|
|
77
|
+
|
|
78
|
+
**Parameters:**
|
|
79
|
+
|
|
80
|
+
- `input` - String, Buffer, or object with `content` property
|
|
81
|
+
- `options` - Optional configuration
|
|
82
|
+
|
|
83
|
+
**Returns:** `GrayMatterFile` object with:
|
|
84
|
+
|
|
85
|
+
- `data` - Parsed front matter data
|
|
86
|
+
- `content` - Content after front matter
|
|
87
|
+
- `excerpt` - Extracted excerpt (if enabled)
|
|
88
|
+
- `orig` - Original input as Buffer
|
|
89
|
+
- `language` - Detected/specified language
|
|
90
|
+
- `matter` - Raw front matter string
|
|
91
|
+
- `isEmpty` - True if front matter block was empty
|
|
92
|
+
- `stringify(data?, options?)` - Stringify the file back
|
|
93
|
+
|
|
94
|
+
### `matter.stringify(file, data?, options?)`
|
|
95
|
+
|
|
96
|
+
Stringify data to front matter and append content.
|
|
97
|
+
|
|
98
|
+
### `matter.read(filepath, options?)`
|
|
99
|
+
|
|
100
|
+
Synchronously read and parse a file.
|
|
101
|
+
|
|
102
|
+
### `matter.test(str, options?)`
|
|
103
|
+
|
|
104
|
+
Test if a string has front matter.
|
|
105
|
+
|
|
106
|
+
### `matter.language(str, options?)`
|
|
107
|
+
|
|
108
|
+
Detect the language specified after the opening delimiter.
|
|
109
|
+
|
|
110
|
+
### Options
|
|
111
|
+
|
|
112
|
+
- `language` - Language to use for parsing (default: `'yaml'`)
|
|
113
|
+
- `delimiters` - Custom delimiters (default: `'---'`)
|
|
114
|
+
- `excerpt` - Enable excerpt extraction (`true`, string delimiter, or function)
|
|
115
|
+
- `excerpt_separator` - Custom excerpt separator
|
|
116
|
+
- `engines` - Custom parsing/stringifying engines
|
|
117
|
+
|
|
118
|
+
## Differences from gray-matter
|
|
119
|
+
|
|
120
|
+
- ESM-only (no CommonJS support)
|
|
121
|
+
- Uses [`@std/yaml`](https://jsr.io/@std/yaml) instead of `js-yaml`
|
|
122
|
+
- Removed JavaScript front matter engine (security: avoids `eval`)
|
|
123
|
+
- Removed deprecated options (`lang`, `delims`, `parsers`)
|
|
124
|
+
- Removed `section-matter` support
|
|
125
|
+
- TypeScript-first with strict types
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { arrayify } from "./utils.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/defaults.ts
|
|
4
|
+
/**
|
|
5
|
+
* Apply default options
|
|
6
|
+
*/
|
|
7
|
+
function defaults(options) {
|
|
8
|
+
const delims = arrayify(options?.delimiters ?? "---");
|
|
9
|
+
const delimiters = delims.length === 1 ? [delims[0], delims[0]] : [delims[0], delims[1]];
|
|
10
|
+
return {
|
|
11
|
+
...options,
|
|
12
|
+
delimiters,
|
|
13
|
+
language: options?.language ?? "yaml"
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { defaults };
|
|
19
|
+
//# sourceMappingURL=defaults.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.mjs","names":[],"sources":["../src/defaults.ts"],"sourcesContent":["import type { GrayMatterOptions, ResolvedOptions } from \"./types.ts\";\nimport { arrayify } from \"./utils.ts\";\n\n/**\n * Apply default options\n */\nexport function defaults(options?: GrayMatterOptions): ResolvedOptions {\n const delims = arrayify(options?.delimiters ?? \"---\");\n const delimiters: [string, string] =\n delims.length === 1 ? [delims[0]!, delims[0]!] : [delims[0]!, delims[1]!];\n\n return {\n ...options,\n delimiters,\n language: options?.language ?? \"yaml\",\n };\n}\n"],"mappings":";;;;;;AAMA,SAAgB,SAAS,SAA8C;CACrE,MAAM,SAAS,SAAS,SAAS,cAAc,MAAM;CACrD,MAAM,aACJ,OAAO,WAAW,IAAI,CAAC,OAAO,IAAK,OAAO,GAAI,GAAG,CAAC,OAAO,IAAK,OAAO,GAAI;AAE3E,QAAO;EACL,GAAG;EACH;EACA,UAAU,SAAS,YAAY;EAChC"}
|
package/dist/engines.mjs
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { toRecord } from "./utils.mjs";
|
|
2
|
+
import { parse } from "./node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/parse.mjs";
|
|
3
|
+
import { stringify } from "./node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/stringify.mjs";
|
|
4
|
+
import "./node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/mod.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/engines.ts
|
|
7
|
+
/**
|
|
8
|
+
* Array of built-in language names for runtime validation
|
|
9
|
+
*/
|
|
10
|
+
const BUILTIN_LANGUAGES = ["yaml", "json"];
|
|
11
|
+
/**
|
|
12
|
+
* Check if value is a built-in language name
|
|
13
|
+
*/
|
|
14
|
+
function isBuiltinLanguage(value) {
|
|
15
|
+
return typeof value === "string" && BUILTIN_LANGUAGES.includes(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Assert that value is a built-in language, returning the default if not
|
|
19
|
+
*/
|
|
20
|
+
function toBuiltinLanguage(value, defaultLang = "yaml") {
|
|
21
|
+
return isBuiltinLanguage(value) ? value : defaultLang;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* YAML engine using @std/yaml
|
|
25
|
+
*/
|
|
26
|
+
const yaml = {
|
|
27
|
+
parse: (str) => {
|
|
28
|
+
return toRecord(parse(str));
|
|
29
|
+
},
|
|
30
|
+
stringify: (data) => {
|
|
31
|
+
return stringify(data);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* JSON engine
|
|
36
|
+
*/
|
|
37
|
+
const json = {
|
|
38
|
+
parse: (str) => {
|
|
39
|
+
return toRecord(JSON.parse(str));
|
|
40
|
+
},
|
|
41
|
+
stringify: (data, options) => {
|
|
42
|
+
const opts = {
|
|
43
|
+
replacer: null,
|
|
44
|
+
space: 2,
|
|
45
|
+
...options
|
|
46
|
+
};
|
|
47
|
+
return JSON.stringify(data, opts.replacer, opts.space);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Get engine by language name
|
|
52
|
+
*/
|
|
53
|
+
function getEngine(language) {
|
|
54
|
+
switch (language) {
|
|
55
|
+
case "yaml": return yaml;
|
|
56
|
+
case "json": return json;
|
|
57
|
+
default: throw new Error(`Unknown language: ${language}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { getEngine, toBuiltinLanguage };
|
|
63
|
+
//# sourceMappingURL=engines.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engines.mjs","names":["yamlParse","yamlStringify"],"sources":["../src/engines.ts"],"sourcesContent":["import { parse as yamlParse, stringify as yamlStringify } from \"@std/yaml\";\nimport type { Engine, GrayMatterOptions } from \"./types.ts\";\nimport { toRecord } from \"./utils.ts\";\n\n/**\n * Built-in language names\n */\nexport type BuiltinLanguage = \"yaml\" | \"json\";\n\n/**\n * Array of built-in language names for runtime validation\n */\nconst BUILTIN_LANGUAGES = [\"yaml\", \"json\"] as const satisfies readonly BuiltinLanguage[];\n\n/**\n * Check if value is a built-in language name\n */\nfunction isBuiltinLanguage(value: unknown): value is BuiltinLanguage {\n return typeof value === \"string\" && BUILTIN_LANGUAGES.includes(value as BuiltinLanguage);\n}\n\n/**\n * Assert that value is a built-in language, returning the default if not\n */\nexport function toBuiltinLanguage(\n value: unknown,\n defaultLang: BuiltinLanguage = \"yaml\",\n): BuiltinLanguage {\n return isBuiltinLanguage(value) ? value : defaultLang;\n}\n\n/**\n * YAML engine using @std/yaml\n */\nconst yaml = {\n parse: (str: string): Record<string, unknown> => {\n return toRecord(yamlParse(str));\n },\n stringify: (data: Record<string, unknown>): string => {\n return yamlStringify(data);\n },\n} as const satisfies Engine;\n\n/**\n * JSON engine\n */\nconst json = {\n parse: (str: string): Record<string, unknown> => {\n return toRecord(JSON.parse(str));\n },\n stringify: (\n data: Record<string, unknown>,\n options?: GrayMatterOptions & { replacer?: null; space?: number },\n ): string => {\n const opts = { replacer: null, space: 2, ...options };\n return JSON.stringify(data, opts.replacer, opts.space);\n },\n} as const satisfies Engine;\n\n/**\n * Get engine by language name\n */\nexport function getEngine(language: BuiltinLanguage): Engine {\n switch (language) {\n case \"yaml\":\n return yaml;\n case \"json\":\n return json;\n default:\n throw new Error(`Unknown language: ${language satisfies never}`);\n }\n}\n\nif (import.meta.vitest) {\n const { fc, test } = await import(\"@fast-check/vitest\");\n\n /** Arbitrary for YAML-safe values (no undefined, functions, symbols) */\n const yamlSafeValue = fc.oneof(\n fc.string(),\n fc.integer(),\n fc.double({ noNaN: true, noDefaultInfinity: true }),\n fc.boolean(),\n fc.constant(null),\n );\n\n /** Arbitrary for simple YAML-compatible objects */\n const yamlSafeObject = fc.dictionary(\n fc.string({ minLength: 1, maxLength: 20 }).filter((s) => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(s)),\n yamlSafeValue,\n { minKeys: 1, maxKeys: 5 },\n );\n\n describe(\"yaml engine\", () => {\n it(\"should parse simple YAML\", () => {\n const result = yaml.parse(\"title: Hello\\ncount: 42\");\n expect(result).toEqual({ title: \"Hello\", count: 42 });\n });\n\n it(\"should return empty object for null YAML\", () => {\n const result = yaml.parse(\"null\");\n expect(result).toEqual({});\n });\n\n it(\"should stringify object to YAML\", () => {\n const result = yaml.stringify({ title: \"Test\", count: 10 });\n expect(result).toContain(\"title: Test\");\n expect(result).toContain(\"count: 10\");\n });\n\n test.prop([yamlSafeObject])(\"should round-trip parse/stringify for safe objects\", (data) => {\n const stringified = yaml.stringify(data);\n const parsed = yaml.parse(stringified);\n expect(parsed).toEqual(data);\n });\n\n test.prop([fc.string({ minLength: 1, maxLength: 100 }), fc.integer()])(\n \"should preserve string and number types\",\n (str, num) => {\n const data = { str, num };\n const stringified = yaml.stringify(data);\n const parsed = yaml.parse(stringified);\n expect(parsed.str).toBe(str);\n expect(parsed.num).toBe(num);\n },\n );\n });\n\n describe(\"json engine\", () => {\n it(\"should parse JSON\", () => {\n const result = json.parse('{\"title\": \"Hello\", \"count\": 42}');\n expect(result).toEqual({ title: \"Hello\", count: 42 });\n });\n\n it(\"should stringify object to JSON\", () => {\n const result = json.stringify({ title: \"Test\" });\n expect(JSON.parse(result)).toEqual({ title: \"Test\" });\n });\n\n it(\"should throw on invalid JSON\", () => {\n expect(() => json.parse(\"not json\")).toThrow();\n });\n\n test.prop([\n fc.record({\n title: fc.string(),\n count: fc.integer(),\n active: fc.boolean(),\n }),\n ])(\"should round-trip parse/stringify\", (data) => {\n const stringified = json.stringify(data);\n const parsed = json.parse(stringified);\n expect(parsed).toEqual(data);\n });\n\n test.prop([\n fc.oneof(\n fc.string(),\n fc.integer(),\n fc.boolean(),\n fc.constant(null),\n fc.array(fc.oneof(fc.string(), fc.integer(), fc.boolean(), fc.constant(null))),\n ),\n ])(\"should handle common JSON values\", (value) => {\n const wrapped = { value };\n const stringified = json.stringify(wrapped);\n const parsed = json.parse(stringified);\n expect(parsed).toEqual(wrapped);\n });\n });\n\n describe(\"getEngine\", () => {\n it(\"should return yaml engine\", () => {\n expect(getEngine(\"yaml\")).toBe(yaml);\n });\n\n it(\"should return json engine\", () => {\n expect(getEngine(\"json\")).toBe(json);\n });\n });\n\n describe(\"isBuiltinLanguage\", () => {\n it(\"should return true for yaml\", () => {\n expect(isBuiltinLanguage(\"yaml\")).toBe(true);\n });\n\n it(\"should return true for json\", () => {\n expect(isBuiltinLanguage(\"json\")).toBe(true);\n });\n\n it(\"should return false for unknown languages\", () => {\n expect(isBuiltinLanguage(\"toml\")).toBe(false);\n expect(isBuiltinLanguage(\"\")).toBe(false);\n });\n\n it(\"should return false for non-strings\", () => {\n expect(isBuiltinLanguage(null)).toBe(false);\n expect(isBuiltinLanguage(undefined)).toBe(false);\n expect(isBuiltinLanguage(123)).toBe(false);\n });\n });\n\n describe(\"toBuiltinLanguage\", () => {\n it(\"should return valid language as-is\", () => {\n expect(toBuiltinLanguage(\"yaml\")).toBe(\"yaml\");\n expect(toBuiltinLanguage(\"json\")).toBe(\"json\");\n });\n\n it(\"should return default for invalid language\", () => {\n expect(toBuiltinLanguage(\"toml\")).toBe(\"yaml\");\n expect(toBuiltinLanguage(\"\")).toBe(\"yaml\");\n });\n\n it(\"should use custom default\", () => {\n expect(toBuiltinLanguage(\"toml\", \"json\")).toBe(\"json\");\n });\n });\n}\n"],"mappings":";;;;;;;;;AAYA,MAAM,oBAAoB,CAAC,QAAQ,OAAO;;;;AAK1C,SAAS,kBAAkB,OAA0C;AACnE,QAAO,OAAO,UAAU,YAAY,kBAAkB,SAAS,MAAyB;;;;;AAM1F,SAAgB,kBACd,OACA,cAA+B,QACd;AACjB,QAAO,kBAAkB,MAAM,GAAG,QAAQ;;;;;AAM5C,MAAM,OAAO;CACX,QAAQ,QAAyC;AAC/C,SAAO,SAASA,MAAU,IAAI,CAAC;;CAEjC,YAAY,SAA0C;AACpD,SAAOC,UAAc,KAAK;;CAE7B;;;;AAKD,MAAM,OAAO;CACX,QAAQ,QAAyC;AAC/C,SAAO,SAAS,KAAK,MAAM,IAAI,CAAC;;CAElC,YACE,MACA,YACW;EACX,MAAM,OAAO;GAAE,UAAU;GAAM,OAAO;GAAG,GAAG;GAAS;AACrD,SAAO,KAAK,UAAU,MAAM,KAAK,UAAU,KAAK,MAAM;;CAEzD;;;;AAKD,SAAgB,UAAU,UAAmC;AAC3D,SAAQ,UAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,OAAM,IAAI,MAAM,qBAAqB,WAA2B"}
|
package/dist/excerpt.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getStringProp } from "./utils.mjs";
|
|
2
|
+
import { defaults } from "./defaults.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/excerpt.ts
|
|
5
|
+
/**
|
|
6
|
+
* Extract excerpt from file content
|
|
7
|
+
*/
|
|
8
|
+
function excerpt(file, options) {
|
|
9
|
+
const opts = defaults(options);
|
|
10
|
+
file.data ??= {};
|
|
11
|
+
if (typeof opts.excerpt === "function") {
|
|
12
|
+
opts.excerpt(file, opts);
|
|
13
|
+
return file;
|
|
14
|
+
}
|
|
15
|
+
const dataSep = getStringProp(file.data, "excerpt_separator");
|
|
16
|
+
const sep = dataSep !== "" ? dataSep : opts.excerpt_separator;
|
|
17
|
+
if (sep == null && (opts.excerpt === false || opts.excerpt == null)) return file;
|
|
18
|
+
const delimiter = typeof opts.excerpt === "string" ? opts.excerpt : sep ?? opts.delimiters[0];
|
|
19
|
+
const idx = file.content.indexOf(delimiter);
|
|
20
|
+
if (idx !== -1) file.excerpt = file.content.slice(0, idx);
|
|
21
|
+
return file;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { excerpt };
|
|
26
|
+
//# sourceMappingURL=excerpt.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"excerpt.mjs","names":[],"sources":["../src/excerpt.ts"],"sourcesContent":["import { defaults } from \"./defaults.ts\";\nimport type { GrayMatterFile, GrayMatterOptions } from \"./types.ts\";\nimport { getStringProp } from \"./utils.ts\";\n\n/**\n * Extract excerpt from file content\n */\nexport function excerpt(file: GrayMatterFile, options?: GrayMatterOptions): GrayMatterFile {\n const opts = defaults(options);\n\n // Ensure data is an object (defensive check for external callers)\n file.data ??= {};\n\n if (typeof opts.excerpt === \"function\") {\n opts.excerpt(file, opts);\n return file;\n }\n\n const dataSep = getStringProp(file.data, \"excerpt_separator\");\n const sep = dataSep !== \"\" ? dataSep : opts.excerpt_separator;\n\n if (sep == null && (opts.excerpt === false || opts.excerpt == null)) {\n return file;\n }\n\n const delimiter = typeof opts.excerpt === \"string\" ? opts.excerpt : (sep ?? opts.delimiters[0]);\n\n // if enabled, get the excerpt defined after front-matter\n const idx = file.content.indexOf(delimiter);\n if (idx !== -1) {\n file.excerpt = file.content.slice(0, idx);\n }\n\n return file;\n}\n\nif (import.meta.vitest) {\n const { fc, test } = await import(\"@fast-check/vitest\");\n const { Buffer } = await import(\"node:buffer\");\n\n const makeFile = (content: string, data: Record<string, unknown> = {}): GrayMatterFile => ({\n content,\n data,\n excerpt: \"\",\n orig: Buffer.from(content),\n language: \"yaml\",\n matter: \"\",\n isEmpty: false,\n stringify: () => \"\",\n });\n\n describe(\"excerpt\", () => {\n it(\"should extract excerpt using default delimiter\", () => {\n const file = makeFile(\"This is excerpt\\n---\\nThis is content\");\n const result = excerpt(file, { excerpt: true });\n expect(result.excerpt).toBe(\"This is excerpt\\n\");\n });\n\n it(\"should extract excerpt using custom string delimiter\", () => {\n const file = makeFile(\"This is excerpt\\n<!-- more -->\\nThis is content\");\n const result = excerpt(file, { excerpt: \"<!-- more -->\" });\n expect(result.excerpt).toBe(\"This is excerpt\\n\");\n });\n\n it(\"should use excerpt_separator from options\", () => {\n const file = makeFile(\"Excerpt here\\n***\\nContent here\");\n const result = excerpt(file, { excerpt: true, excerpt_separator: \"***\" });\n expect(result.excerpt).toBe(\"Excerpt here\\n\");\n });\n\n it(\"should use excerpt_separator from file.data\", () => {\n const file = makeFile(\"Excerpt\\n<!-- end -->\\nContent\", {\n excerpt_separator: \"<!-- end -->\",\n });\n const result = excerpt(file, { excerpt: true });\n expect(result.excerpt).toBe(\"Excerpt\\n\");\n });\n\n it(\"should not extract when excerpt is false\", () => {\n const file = makeFile(\"Some content\\n---\\nMore content\");\n const result = excerpt(file, { excerpt: false });\n expect(result.excerpt).toBe(\"\");\n });\n\n it(\"should not modify when delimiter not found\", () => {\n const file = makeFile(\"No delimiter here\");\n const result = excerpt(file, { excerpt: true });\n expect(result.excerpt).toBe(\"\");\n });\n\n it(\"should call custom excerpt function\", () => {\n const file = makeFile(\"Custom content\");\n const customFn = vi.fn((f: GrayMatterFile) => {\n f.excerpt = \"Custom excerpt\";\n });\n const result = excerpt(file, { excerpt: customFn });\n expect(customFn).toHaveBeenCalledOnce();\n expect(result.excerpt).toBe(\"Custom excerpt\");\n });\n\n it(\"should initialize file.data if null\", () => {\n const file = makeFile(\"content\");\n file.data = null as unknown as Record<string, unknown>;\n const result = excerpt(file, {});\n expect(result.data).toEqual({});\n });\n\n test.prop([\n fc.string({ minLength: 1, maxLength: 50 }),\n fc.string({ minLength: 1, maxLength: 50 }),\n ])(\"should extract correct excerpt when delimiter exists\", (excerptText, contentText) => {\n const delimiter = \"---\";\n const content = `${excerptText}\\n${delimiter}\\n${contentText}`;\n const file = makeFile(content);\n const result = excerpt(file, { excerpt: true });\n\n expect(result.excerpt).toBe(`${excerptText}\\n`);\n });\n\n test.prop([fc.string({ minLength: 1, maxLength: 100 })])(\n \"should not extract when no delimiter in content\",\n (content) => {\n const safeContent = content.replace(/---/g, \"___\");\n const file = makeFile(safeContent);\n const result = excerpt(file, { excerpt: true });\n expect(result.excerpt).toBe(\"\");\n },\n );\n\n test.prop([\n fc.string({ minLength: 1, maxLength: 20 }),\n fc.string({ minLength: 1, maxLength: 20 }),\n fc\n .string({ minLength: 1, maxLength: 10 })\n .filter((s) => !s.includes(\"\\n\") && !/[[\\]{}()*+?.,\\\\^$|#]/.test(s)),\n ])(\"should work with any custom delimiter\", (excerptText, contentText, customDelimiter) => {\n const safeExcerpt = excerptText.replaceAll(customDelimiter, \"\");\n if (safeExcerpt === \"\") return;\n const content = `${safeExcerpt}\\n${customDelimiter}\\n${contentText}`;\n const file = makeFile(content);\n const result = excerpt(file, { excerpt: customDelimiter });\n\n expect(result.excerpt).toBe(`${safeExcerpt}\\n`);\n });\n });\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,QAAQ,MAAsB,SAA6C;CACzF,MAAM,OAAO,SAAS,QAAQ;AAG9B,MAAK,SAAS,EAAE;AAEhB,KAAI,OAAO,KAAK,YAAY,YAAY;AACtC,OAAK,QAAQ,MAAM,KAAK;AACxB,SAAO;;CAGT,MAAM,UAAU,cAAc,KAAK,MAAM,oBAAoB;CAC7D,MAAM,MAAM,YAAY,KAAK,UAAU,KAAK;AAE5C,KAAI,OAAO,SAAS,KAAK,YAAY,SAAS,KAAK,WAAW,MAC5D,QAAO;CAGT,MAAM,YAAY,OAAO,KAAK,YAAY,WAAW,KAAK,UAAW,OAAO,KAAK,WAAW;CAG5F,MAAM,MAAM,KAAK,QAAQ,QAAQ,UAAU;AAC3C,KAAI,QAAQ,GACV,MAAK,UAAU,KAAK,QAAQ,MAAM,GAAG,IAAI;AAG3C,QAAO"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Engine, GrayMatterFile, GrayMatterInput, GrayMatterOptions, MatterFunction, ResolvedOptions } from "./types.mjs";
|
|
2
|
+
import { BuiltinLanguage } from "./engines.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The matter function with all static methods
|
|
8
|
+
*/
|
|
9
|
+
declare const matter: MatterFunction;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type BuiltinLanguage, type Engine, type GrayMatterFile, type GrayMatterInput, type GrayMatterOptions, type MatterFunction, type ResolvedOptions, matter as default };
|
|
12
|
+
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { defaults } from "./defaults.mjs";
|
|
2
|
+
import { toBuiltinLanguage } from "./engines.mjs";
|
|
3
|
+
import { excerpt } from "./excerpt.mjs";
|
|
4
|
+
import { parse } from "./parse.mjs";
|
|
5
|
+
import { stringify } from "./stringify.mjs";
|
|
6
|
+
import { toFile } from "./to-file.mjs";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
|
|
9
|
+
//#region src/index.ts
|
|
10
|
+
/**
|
|
11
|
+
* Cache for parsed results
|
|
12
|
+
*/
|
|
13
|
+
const cache = /* @__PURE__ */ new Map();
|
|
14
|
+
/**
|
|
15
|
+
* Takes a string or object with `content` property, extracts
|
|
16
|
+
* and parses front-matter from the string, then returns an object
|
|
17
|
+
* with `data`, `content` and other useful properties.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import matter from 'gray-matter-es';
|
|
22
|
+
* console.log(matter('---\ntitle: Home\n---\nOther stuff'));
|
|
23
|
+
* //=> { data: { title: 'Home'}, content: 'Other stuff' }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
function matterImpl(input, options) {
|
|
27
|
+
if (input === "") return {
|
|
28
|
+
...toFile(input),
|
|
29
|
+
isEmpty: true
|
|
30
|
+
};
|
|
31
|
+
let file = toFile(input);
|
|
32
|
+
const cached = cache.get(file.content);
|
|
33
|
+
if (!options) {
|
|
34
|
+
if (cached) {
|
|
35
|
+
file = { ...cached };
|
|
36
|
+
file.orig = cached.orig;
|
|
37
|
+
return file;
|
|
38
|
+
}
|
|
39
|
+
cache.set(file.content, file);
|
|
40
|
+
}
|
|
41
|
+
return parseMatter(file, options);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse front matter from file
|
|
45
|
+
*/
|
|
46
|
+
function parseMatter(file, options) {
|
|
47
|
+
const opts = defaults(options);
|
|
48
|
+
const open = opts.delimiters[0];
|
|
49
|
+
const close = "\n" + opts.delimiters[1];
|
|
50
|
+
let str = file.content;
|
|
51
|
+
if (opts.language) file.language = opts.language;
|
|
52
|
+
const openLen = open.length;
|
|
53
|
+
if (!str.startsWith(open)) {
|
|
54
|
+
excerpt(file, opts);
|
|
55
|
+
return file;
|
|
56
|
+
}
|
|
57
|
+
if (str.at(openLen) === open.at(-1)) return file;
|
|
58
|
+
str = str.slice(openLen);
|
|
59
|
+
const len = str.length;
|
|
60
|
+
const lang = matterLanguage(str, opts);
|
|
61
|
+
if (lang.name) {
|
|
62
|
+
file.language = lang.name;
|
|
63
|
+
str = str.slice(lang.raw.length);
|
|
64
|
+
}
|
|
65
|
+
let closeIndex = str.indexOf(close);
|
|
66
|
+
if (closeIndex === -1) closeIndex = len;
|
|
67
|
+
file.matter = str.slice(0, closeIndex);
|
|
68
|
+
if (file.matter.replace(/^\s*#[^\n]+/gm, "").trim() === "") {
|
|
69
|
+
file.isEmpty = true;
|
|
70
|
+
file.empty = file.content;
|
|
71
|
+
file.data = {};
|
|
72
|
+
} else file.data = parse(toBuiltinLanguage(file.language), file.matter);
|
|
73
|
+
if (closeIndex === len) file.content = "";
|
|
74
|
+
else {
|
|
75
|
+
file.content = str.slice(closeIndex + close.length);
|
|
76
|
+
if (file.content.at(0) === "\r") file.content = file.content.slice(1);
|
|
77
|
+
if (file.content.at(0) === "\n") file.content = file.content.slice(1);
|
|
78
|
+
}
|
|
79
|
+
excerpt(file, opts);
|
|
80
|
+
return file;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Detect the language to use, if one is defined after the
|
|
84
|
+
* first front-matter delimiter.
|
|
85
|
+
*/
|
|
86
|
+
function matterLanguage(str, options) {
|
|
87
|
+
const opts = defaults(options);
|
|
88
|
+
const open = opts.delimiters[0];
|
|
89
|
+
if (matterTest(str, opts)) str = str.slice(open.length);
|
|
90
|
+
const language = str.slice(0, str.search(/\r?\n/));
|
|
91
|
+
return {
|
|
92
|
+
raw: language,
|
|
93
|
+
name: language ? language.trim() : ""
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns true if the given string has front matter.
|
|
98
|
+
*/
|
|
99
|
+
function matterTest(str, options) {
|
|
100
|
+
return str.startsWith(defaults(options).delimiters[0]);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The matter function with all static methods
|
|
104
|
+
*/
|
|
105
|
+
const matter = Object.assign(matterImpl, {
|
|
106
|
+
stringify: (file, data, options) => {
|
|
107
|
+
if (typeof file === "string") file = matterImpl(file, options);
|
|
108
|
+
return stringify(file, data, options);
|
|
109
|
+
},
|
|
110
|
+
read: (filepath, options) => {
|
|
111
|
+
const file = matterImpl(readFileSync(filepath, "utf8"), options);
|
|
112
|
+
file.path = filepath;
|
|
113
|
+
return file;
|
|
114
|
+
},
|
|
115
|
+
test: matterTest,
|
|
116
|
+
language: matterLanguage,
|
|
117
|
+
clearCache: () => {
|
|
118
|
+
cache.clear();
|
|
119
|
+
},
|
|
120
|
+
cache
|
|
121
|
+
});
|
|
122
|
+
var src_default = matter;
|
|
123
|
+
|
|
124
|
+
//#endregion
|
|
125
|
+
export { src_default as default };
|
|
126
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { defaults } from \"./defaults.ts\";\nimport { toBuiltinLanguage } from \"./engines.ts\";\nimport { excerpt } from \"./excerpt.ts\";\nimport { parse } from \"./parse.ts\";\nimport { stringify } from \"./stringify.ts\";\nimport { toFile } from \"./to-file.ts\";\nimport type {\n GrayMatterFile,\n GrayMatterInput,\n GrayMatterOptions,\n MatterFunction,\n} from \"./types.ts\";\n\nexport type {\n Engine,\n GrayMatterFile,\n GrayMatterInput,\n GrayMatterOptions,\n MatterFunction,\n ResolvedOptions,\n} from \"./types.ts\";\n\nexport type { BuiltinLanguage } from \"./engines.ts\";\n\n/**\n * Cache for parsed results\n */\nconst cache = new Map<string, GrayMatterFile>();\n\n/**\n * Takes a string or object with `content` property, extracts\n * and parses front-matter from the string, then returns an object\n * with `data`, `content` and other useful properties.\n *\n * @example\n * ```ts\n * import matter from 'gray-matter-es';\n * console.log(matter('---\\ntitle: Home\\n---\\nOther stuff'));\n * //=> { data: { title: 'Home'}, content: 'Other stuff' }\n * ```\n */\nfunction matterImpl(input: GrayMatterInput, options?: GrayMatterOptions): GrayMatterFile {\n if (input === \"\") {\n return { ...toFile(input), isEmpty: true };\n }\n\n let file = toFile(input);\n const cached = cache.get(file.content);\n\n if (!options) {\n if (cached) {\n file = { ...cached };\n file.orig = cached.orig;\n return file;\n }\n\n // only cache if there are no options passed\n cache.set(file.content, file);\n }\n\n return parseMatter(file, options);\n}\n\n/**\n * Parse front matter from file\n */\nfunction parseMatter(file: GrayMatterFile, options?: GrayMatterOptions): GrayMatterFile {\n const opts = defaults(options);\n const open = opts.delimiters[0];\n const close = \"\\n\" + opts.delimiters[1];\n let str = file.content;\n\n if (opts.language) {\n file.language = opts.language;\n }\n\n // get the length of the opening delimiter\n const openLen = open.length;\n if (!str.startsWith(open)) {\n excerpt(file, opts);\n return file;\n }\n\n // if the next character after the opening delimiter is\n // a character from the delimiter, then it's not a front-\n // matter delimiter\n if (str.at(openLen) === open.at(-1)) {\n return file;\n }\n\n // strip the opening delimiter\n str = str.slice(openLen);\n const len = str.length;\n\n // use the language defined after first delimiter, if it exists\n const lang = matterLanguage(str, opts);\n if (lang.name) {\n file.language = lang.name;\n str = str.slice(lang.raw.length);\n }\n\n // get the index of the closing delimiter\n let closeIndex = str.indexOf(close);\n if (closeIndex === -1) {\n closeIndex = len;\n }\n\n // get the raw front-matter block\n file.matter = str.slice(0, closeIndex);\n\n const block = file.matter.replace(/^\\s*#[^\\n]+/gm, \"\").trim();\n if (block === \"\") {\n file.isEmpty = true;\n file.empty = file.content;\n file.data = {};\n } else {\n // create file.data by parsing the raw file.matter block\n file.data = parse(toBuiltinLanguage(file.language), file.matter);\n }\n\n // update file.content\n if (closeIndex === len) {\n file.content = \"\";\n } else {\n file.content = str.slice(closeIndex + close.length);\n if (file.content.at(0) === \"\\r\") {\n file.content = file.content.slice(1);\n }\n if (file.content.at(0) === \"\\n\") {\n file.content = file.content.slice(1);\n }\n }\n\n excerpt(file, opts);\n return file;\n}\n\n/**\n * Detect the language to use, if one is defined after the\n * first front-matter delimiter.\n */\nfunction matterLanguage(str: string, options?: GrayMatterOptions): { raw: string; name: string } {\n const opts = defaults(options);\n const open = opts.delimiters[0];\n\n if (matterTest(str, opts)) {\n str = str.slice(open.length);\n }\n\n const language = str.slice(0, str.search(/\\r?\\n/));\n return {\n raw: language,\n name: language ? language.trim() : \"\",\n };\n}\n\n/**\n * Returns true if the given string has front matter.\n */\nfunction matterTest(str: string, options?: GrayMatterOptions): boolean {\n return str.startsWith(defaults(options).delimiters[0]);\n}\n\n/**\n * The matter function with all static methods\n */\nconst matter: MatterFunction = Object.assign(matterImpl, {\n /**\n * Stringify an object to YAML or the specified language, and\n * append it to the given string.\n */\n stringify: (\n file: GrayMatterFile | string,\n data?: Record<string, unknown>,\n options?: GrayMatterOptions,\n ): string => {\n if (typeof file === \"string\") file = matterImpl(file, options);\n return stringify(file, data, options);\n },\n\n /**\n * Synchronously read a file from the file system and parse front matter.\n */\n read: (filepath: string, options?: GrayMatterOptions): GrayMatterFile => {\n const str = readFileSync(filepath, \"utf8\");\n const file = matterImpl(str, options);\n file.path = filepath;\n return file;\n },\n\n /**\n * Returns true if the given string has front matter.\n */\n test: matterTest,\n\n /**\n * Detect the language to use, if one is defined after the\n * first front-matter delimiter.\n */\n language: matterLanguage,\n\n /**\n * Clear the cache\n */\n clearCache: (): void => {\n cache.clear();\n },\n\n /**\n * Expose cache (read-only access)\n */\n cache,\n});\n\nexport default matter;\n\nif (import.meta.vitest) {\n const { fc, test } = await import(\"@fast-check/vitest\");\n const { Buffer } = await import(\"node:buffer\");\n\n describe(\"matter\", () => {\n beforeEach(() => {\n matter.clearCache();\n });\n\n it(\"should extract YAML front matter\", () => {\n const actual = matter(\"---\\nabc: xyz\\n---\");\n expect(actual.data).toEqual({ abc: \"xyz\" });\n expect(actual.content).toBe(\"\");\n });\n\n it(\"should extract YAML front matter with content\", () => {\n const actual = matter(\"---\\nabc: xyz\\n---\\nfoo\");\n expect(actual.data).toEqual({ abc: \"xyz\" });\n expect(actual.content).toBe(\"foo\");\n });\n\n it(\"should return empty object for empty string\", () => {\n const actual = matter(\"\");\n expect(actual.data).toEqual({});\n expect(actual.content).toBe(\"\");\n });\n\n it(\"should return content when no front matter\", () => {\n const actual = matter(\"foo bar\");\n expect(actual.data).toEqual({});\n expect(actual.content).toBe(\"foo bar\");\n });\n\n it(\"should handle CRLF line endings\", () => {\n const actual = matter(\"---\\r\\nabc: xyz\\r\\n---\\r\\ncontent\");\n expect(actual.data).toEqual({ abc: \"xyz\" });\n expect(actual.content).toBe(\"content\");\n });\n\n it(\"should detect language after delimiter\", () => {\n const actual = matter('---json\\n{\"abc\": \"xyz\"}\\n---\\ncontent');\n expect(actual.data).toEqual({ abc: \"xyz\" });\n expect(actual.language).toBe(\"json\");\n });\n\n it(\"should handle custom delimiters\", () => {\n const actual = matter(\"~~~\\nabc: xyz\\n~~~\\ncontent\", {\n delimiters: \"~~~\",\n });\n expect(actual.data).toEqual({ abc: \"xyz\" });\n });\n\n it(\"should extract excerpt when enabled\", () => {\n const actual = matter(\"---\\nabc: xyz\\n---\\nexcerpt\\n---\\ncontent\", {\n excerpt: true,\n });\n expect(actual.excerpt).toBe(\"excerpt\\n\");\n });\n\n it(\"should use custom excerpt separator\", () => {\n const actual = matter(\"---\\nabc: xyz\\n---\\nexcerpt\\n<!-- more -->\\ncontent\", {\n excerpt: true,\n excerpt_separator: \"<!-- more -->\",\n });\n expect(actual.excerpt).toBe(\"excerpt\\n\");\n });\n\n it(\"should cache results when no options\", () => {\n const input = \"---\\nabc: xyz\\n---\";\n const first = matter(input);\n const second = matter(input);\n expect(first.data).toEqual(second.data);\n });\n\n it(\"should not cache when options provided\", () => {\n const input = \"---\\nabc: xyz\\n---\";\n matter(input);\n const second = matter(input, { language: \"yaml\" });\n expect(second.data).toEqual({ abc: \"xyz\" });\n });\n });\n\n describe(\"matter.stringify\", () => {\n it(\"should stringify data to YAML front matter\", () => {\n const result = matter.stringify(\"content\", { title: \"Hello\" });\n expect(result).toContain(\"---\");\n expect(result).toContain(\"title: Hello\");\n expect(result).toContain(\"content\");\n });\n\n it(\"should stringify file object\", () => {\n const file = matter(\"---\\ntitle: Test\\n---\\ncontent\");\n const result = matter.stringify(file, { title: \"Updated\" });\n expect(result).toContain(\"title: Updated\");\n });\n });\n\n describe(\"matter.test\", () => {\n it(\"should return true for string with front matter\", () => {\n expect(matter.test(\"---\\nabc: xyz\\n---\")).toBe(true);\n });\n\n it(\"should return false for string without front matter\", () => {\n expect(matter.test(\"foo bar\")).toBe(false);\n });\n });\n\n describe(\"matter.language\", () => {\n it(\"should detect language after delimiter\", () => {\n const result = matter.language(\"---json\\n{}\\n---\");\n expect(result.name).toBe(\"json\");\n });\n\n it(\"should return empty for no language\", () => {\n const result = matter.language(\"---\\nabc: xyz\\n---\");\n expect(result.name).toBe(\"\");\n });\n });\n\n describe(\"property-based tests\", () => {\n beforeEach(() => {\n matter.clearCache();\n });\n\n /** Arbitrary for YAML-safe keys */\n const yamlKey = fc\n .string({ minLength: 1, maxLength: 20 })\n .filter((s) => /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(s));\n\n /** Arbitrary for YAML-safe values */\n const yamlSafeValue = fc.oneof(\n fc.string({ maxLength: 50 }),\n fc.integer({ min: -10000, max: 10000 }),\n fc.boolean(),\n );\n\n /** Arbitrary for simple YAML-compatible objects */\n const yamlSafeObject = fc.dictionary(yamlKey, yamlSafeValue, { minKeys: 1, maxKeys: 5 });\n\n test.prop([fc.string({ minLength: 1, maxLength: 100 })])(\n \"Buffer and string input should produce equivalent results\",\n (content) => {\n matter.clearCache();\n const fromString = matter(content);\n matter.clearCache();\n const fromBuffer = matter(Buffer.from(content));\n\n expect(fromString.content).toBe(fromBuffer.content);\n expect(fromString.data).toEqual(fromBuffer.data);\n expect(fromString.excerpt).toBe(fromBuffer.excerpt);\n },\n );\n\n test.prop([yamlSafeObject, fc.string({ minLength: 0, maxLength: 50 })])(\n \"parse then stringify should preserve data\",\n (data, content) => {\n const frontMatter = Object.entries(data)\n .map(([k, v]) => `${k}: ${typeof v === \"string\" ? JSON.stringify(v) : v}`)\n .join(\"\\n\");\n const input = `---\\n${frontMatter}\\n---\\n${content}`;\n\n matter.clearCache();\n const parsed = matter(input);\n const stringified = matter.stringify(parsed);\n matter.clearCache();\n const reparsed = matter(stringified);\n\n expect(reparsed.data).toEqual(parsed.data);\n },\n );\n\n test.prop([fc.string({ minLength: 0, maxLength: 100 })])(\n \"content without front matter should be preserved\",\n (content) => {\n const safeContent = content.replace(/^---/gm, \"___\");\n matter.clearCache();\n const result = matter(safeContent);\n\n expect(result.content).toBe(safeContent);\n expect(result.data).toEqual({});\n },\n );\n\n test.prop([\n yamlSafeObject,\n fc.string({ minLength: 0, maxLength: 50 }),\n fc.string({ minLength: 1, maxLength: 50 }),\n ])(\"matter.test should correctly detect front matter\", (data, content, noFrontMatter) => {\n const frontMatter = Object.entries(data)\n .map(([k, v]) => `${k}: ${typeof v === \"string\" ? JSON.stringify(v) : v}`)\n .join(\"\\n\");\n const withFrontMatter = `---\\n${frontMatter}\\n---\\n${content}`;\n const withoutFrontMatter = noFrontMatter.replace(/^---/gm, \"___\");\n\n expect(matter.test(withFrontMatter)).toBe(true);\n expect(matter.test(withoutFrontMatter)).toBe(withoutFrontMatter.startsWith(\"---\"));\n });\n\n test.prop([fc.constantFrom(\"yaml\", \"json\"), yamlSafeObject, fc.string({ maxLength: 30 })])(\n \"should handle different languages\",\n (language, data, content) => {\n let frontMatterContent: string;\n if (language === \"json\") {\n frontMatterContent = JSON.stringify(data);\n } else {\n frontMatterContent = Object.entries(data)\n .map(([k, v]) => `${k}: ${typeof v === \"string\" ? JSON.stringify(v) : v}`)\n .join(\"\\n\");\n }\n\n const input = `---${language}\\n${frontMatterContent}\\n---\\n${content}`;\n matter.clearCache();\n const result = matter(input);\n\n expect(result.language).toBe(language);\n expect(result.data).toEqual(data);\n },\n );\n\n test.prop([fc.constantFrom(\"---\", \"~~~\", \"***\", \"+++\")])(\n \"should handle custom delimiters\",\n (delimiter) => {\n const input = `${delimiter}\\ntitle: Test\\n${delimiter}\\ncontent`;\n matter.clearCache();\n const result = matter(input, { delimiters: delimiter });\n\n expect(result.data).toEqual({ title: \"Test\" });\n expect(result.content).toBe(\"content\");\n },\n );\n\n test.prop([\n fc.string({ minLength: 1, maxLength: 20 }),\n fc.string({ minLength: 1, maxLength: 20 }),\n ])(\"should extract excerpt with custom separator\", (excerptText, contentText) => {\n const separator = \"<!-- more -->\";\n const safeExcerpt = excerptText.replace(separator, \"\");\n const safeContent = contentText.replace(separator, \"\");\n const input = `---\\ntitle: Test\\n---\\n${safeExcerpt}\\n${separator}\\n${safeContent}`;\n\n matter.clearCache();\n const result = matter(input, { excerpt: true, excerpt_separator: separator });\n\n expect(result.excerpt).toBe(`${safeExcerpt}\\n`);\n });\n\n test.prop([fc.string({ minLength: 0, maxLength: 50 })])(\n \"should handle CRLF and LF consistently\",\n (content) => {\n const yamlData = \"title: Test\";\n const inputLF = `---\\n${yamlData}\\n---\\n${content}`;\n const inputCRLF = `---\\r\\n${yamlData}\\r\\n---\\r\\n${content}`;\n\n matter.clearCache();\n const resultLF = matter(inputLF);\n matter.clearCache();\n const resultCRLF = matter(inputCRLF);\n\n expect(resultLF.data).toEqual(resultCRLF.data);\n expect(resultLF.content).toBe(resultCRLF.content);\n },\n );\n });\n}\n"],"mappings":";;;;;;;;;;;;AA4BA,MAAM,wBAAQ,IAAI,KAA6B;;;;;;;;;;;;;AAc/C,SAAS,WAAW,OAAwB,SAA6C;AACvF,KAAI,UAAU,GACZ,QAAO;EAAE,GAAG,OAAO,MAAM;EAAE,SAAS;EAAM;CAG5C,IAAI,OAAO,OAAO,MAAM;CACxB,MAAM,SAAS,MAAM,IAAI,KAAK,QAAQ;AAEtC,KAAI,CAAC,SAAS;AACZ,MAAI,QAAQ;AACV,UAAO,EAAE,GAAG,QAAQ;AACpB,QAAK,OAAO,OAAO;AACnB,UAAO;;AAIT,QAAM,IAAI,KAAK,SAAS,KAAK;;AAG/B,QAAO,YAAY,MAAM,QAAQ;;;;;AAMnC,SAAS,YAAY,MAAsB,SAA6C;CACtF,MAAM,OAAO,SAAS,QAAQ;CAC9B,MAAM,OAAO,KAAK,WAAW;CAC7B,MAAM,QAAQ,OAAO,KAAK,WAAW;CACrC,IAAI,MAAM,KAAK;AAEf,KAAI,KAAK,SACP,MAAK,WAAW,KAAK;CAIvB,MAAM,UAAU,KAAK;AACrB,KAAI,CAAC,IAAI,WAAW,KAAK,EAAE;AACzB,UAAQ,MAAM,KAAK;AACnB,SAAO;;AAMT,KAAI,IAAI,GAAG,QAAQ,KAAK,KAAK,GAAG,GAAG,CACjC,QAAO;AAIT,OAAM,IAAI,MAAM,QAAQ;CACxB,MAAM,MAAM,IAAI;CAGhB,MAAM,OAAO,eAAe,KAAK,KAAK;AACtC,KAAI,KAAK,MAAM;AACb,OAAK,WAAW,KAAK;AACrB,QAAM,IAAI,MAAM,KAAK,IAAI,OAAO;;CAIlC,IAAI,aAAa,IAAI,QAAQ,MAAM;AACnC,KAAI,eAAe,GACjB,cAAa;AAIf,MAAK,SAAS,IAAI,MAAM,GAAG,WAAW;AAGtC,KADc,KAAK,OAAO,QAAQ,iBAAiB,GAAG,CAAC,MAAM,KAC/C,IAAI;AAChB,OAAK,UAAU;AACf,OAAK,QAAQ,KAAK;AAClB,OAAK,OAAO,EAAE;OAGd,MAAK,OAAO,MAAM,kBAAkB,KAAK,SAAS,EAAE,KAAK,OAAO;AAIlE,KAAI,eAAe,IACjB,MAAK,UAAU;MACV;AACL,OAAK,UAAU,IAAI,MAAM,aAAa,MAAM,OAAO;AACnD,MAAI,KAAK,QAAQ,GAAG,EAAE,KAAK,KACzB,MAAK,UAAU,KAAK,QAAQ,MAAM,EAAE;AAEtC,MAAI,KAAK,QAAQ,GAAG,EAAE,KAAK,KACzB,MAAK,UAAU,KAAK,QAAQ,MAAM,EAAE;;AAIxC,SAAQ,MAAM,KAAK;AACnB,QAAO;;;;;;AAOT,SAAS,eAAe,KAAa,SAA4D;CAC/F,MAAM,OAAO,SAAS,QAAQ;CAC9B,MAAM,OAAO,KAAK,WAAW;AAE7B,KAAI,WAAW,KAAK,KAAK,CACvB,OAAM,IAAI,MAAM,KAAK,OAAO;CAG9B,MAAM,WAAW,IAAI,MAAM,GAAG,IAAI,OAAO,QAAQ,CAAC;AAClD,QAAO;EACL,KAAK;EACL,MAAM,WAAW,SAAS,MAAM,GAAG;EACpC;;;;;AAMH,SAAS,WAAW,KAAa,SAAsC;AACrE,QAAO,IAAI,WAAW,SAAS,QAAQ,CAAC,WAAW,GAAG;;;;;AAMxD,MAAM,SAAyB,OAAO,OAAO,YAAY;CAKvD,YACE,MACA,MACA,YACW;AACX,MAAI,OAAO,SAAS,SAAU,QAAO,WAAW,MAAM,QAAQ;AAC9D,SAAO,UAAU,MAAM,MAAM,QAAQ;;CAMvC,OAAO,UAAkB,YAAgD;EAEvE,MAAM,OAAO,WADD,aAAa,UAAU,OAAO,EACb,QAAQ;AACrC,OAAK,OAAO;AACZ,SAAO;;CAMT,MAAM;CAMN,UAAU;CAKV,kBAAwB;AACtB,QAAM,OAAO;;CAMf;CACD,CAAC;AAEF,kBAAe"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region node_modules/.pnpm/@jsr+std__yaml@1.0.10/node_modules/@jsr/std__yaml/_chars.js
|
|
2
|
+
const BOM = 65279;
|
|
3
|
+
const TAB = 9;
|
|
4
|
+
const LINE_FEED = 10;
|
|
5
|
+
const CARRIAGE_RETURN = 13;
|
|
6
|
+
const SPACE = 32;
|
|
7
|
+
const EXCLAMATION = 33;
|
|
8
|
+
const DOUBLE_QUOTE = 34;
|
|
9
|
+
const SHARP = 35;
|
|
10
|
+
const PERCENT = 37;
|
|
11
|
+
const AMPERSAND = 38;
|
|
12
|
+
const SINGLE_QUOTE = 39;
|
|
13
|
+
const ASTERISK = 42;
|
|
14
|
+
const PLUS = 43;
|
|
15
|
+
const COMMA = 44;
|
|
16
|
+
const MINUS = 45;
|
|
17
|
+
const DOT = 46;
|
|
18
|
+
const COLON = 58;
|
|
19
|
+
const SMALLER_THAN = 60;
|
|
20
|
+
const GREATER_THAN = 62;
|
|
21
|
+
const QUESTION = 63;
|
|
22
|
+
const COMMERCIAL_AT = 64;
|
|
23
|
+
const LEFT_SQUARE_BRACKET = 91;
|
|
24
|
+
const BACKSLASH = 92;
|
|
25
|
+
const RIGHT_SQUARE_BRACKET = 93;
|
|
26
|
+
const GRAVE_ACCENT = 96;
|
|
27
|
+
const LEFT_CURLY_BRACKET = 123;
|
|
28
|
+
const VERTICAL_LINE = 124;
|
|
29
|
+
const RIGHT_CURLY_BRACKET = 125;
|
|
30
|
+
function isEOL(c) {
|
|
31
|
+
return c === LINE_FEED || c === CARRIAGE_RETURN;
|
|
32
|
+
}
|
|
33
|
+
function isWhiteSpace(c) {
|
|
34
|
+
return c === TAB || c === SPACE;
|
|
35
|
+
}
|
|
36
|
+
function isWhiteSpaceOrEOL(c) {
|
|
37
|
+
return isWhiteSpace(c) || isEOL(c);
|
|
38
|
+
}
|
|
39
|
+
function isFlowIndicator(c) {
|
|
40
|
+
return c === COMMA || c === LEFT_SQUARE_BRACKET || c === RIGHT_SQUARE_BRACKET || c === LEFT_CURLY_BRACKET || c === RIGHT_CURLY_BRACKET;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { AMPERSAND, ASTERISK, BACKSLASH, BOM, CARRIAGE_RETURN, COLON, COMMA, COMMERCIAL_AT, DOT, DOUBLE_QUOTE, EXCLAMATION, GRAVE_ACCENT, GREATER_THAN, LEFT_CURLY_BRACKET, LEFT_SQUARE_BRACKET, LINE_FEED, MINUS, PERCENT, PLUS, QUESTION, RIGHT_CURLY_BRACKET, RIGHT_SQUARE_BRACKET, SHARP, SINGLE_QUOTE, SMALLER_THAN, SPACE, VERTICAL_LINE, isEOL, isFlowIndicator, isWhiteSpace, isWhiteSpaceOrEOL };
|
|
45
|
+
//# sourceMappingURL=_chars.mjs.map
|
package/dist/node_modules/.pnpm/@jsr_std__yaml@1.0.10/node_modules/@jsr/std__yaml/_chars.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_chars.mjs","names":[],"sources":["../../../../../../../node_modules/.pnpm/@jsr+std__yaml@1.0.10/node_modules/@jsr/std__yaml/_chars.js"],"sourcesContent":["// Ported from js-yaml v3.13.1:\n// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da\n// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.\n// Copyright 2018-2025 the Deno authors. MIT license.\nexport const BOM = 0xfeff; /* BOM */ \nexport const TAB = 0x09; /* Tab */ \nexport const LINE_FEED = 0x0a; /* LF */ \nexport const CARRIAGE_RETURN = 0x0d; /* CR */ \nexport const SPACE = 0x20; /* Space */ \nexport const EXCLAMATION = 0x21; /* ! */ \nexport const DOUBLE_QUOTE = 0x22; /* \" */ \nexport const SHARP = 0x23; /* # */ \nexport const PERCENT = 0x25; /* % */ \nexport const AMPERSAND = 0x26; /* & */ \nexport const SINGLE_QUOTE = 0x27; /* ' */ \nexport const ASTERISK = 0x2a; /* * */ \nexport const PLUS = 0x2b; /* + */ \nexport const COMMA = 0x2c; /* , */ \nexport const MINUS = 0x2d; /* - */ \nexport const DOT = 0x2e; /* . */ \nexport const COLON = 0x3a; /* : */ \nexport const SMALLER_THAN = 0x3c; /* < */ \nexport const GREATER_THAN = 0x3e; /* > */ \nexport const QUESTION = 0x3f; /* ? */ \nexport const COMMERCIAL_AT = 0x40; /* @ */ \nexport const LEFT_SQUARE_BRACKET = 0x5b; /* [ */ \nexport const BACKSLASH = 0x5c; /* \\ */ \nexport const RIGHT_SQUARE_BRACKET = 0x5d; /* ] */ \nexport const GRAVE_ACCENT = 0x60; /* ` */ \nexport const LEFT_CURLY_BRACKET = 0x7b; /* { */ \nexport const VERTICAL_LINE = 0x7c; /* | */ \nexport const RIGHT_CURLY_BRACKET = 0x7d; /* } */ \nexport function isEOL(c) {\n return c === LINE_FEED || c === CARRIAGE_RETURN;\n}\nexport function isWhiteSpace(c) {\n return c === TAB || c === SPACE;\n}\nexport function isWhiteSpaceOrEOL(c) {\n return isWhiteSpace(c) || isEOL(c);\n}\nexport function isFlowIndicator(c) {\n return c === COMMA || c === LEFT_SQUARE_BRACKET || c === RIGHT_SQUARE_BRACKET || c === LEFT_CURLY_BRACKET || c === RIGHT_CURLY_BRACKET;\n}\n//# sourceMappingURL=_chars.js.map"],"x_google_ignoreList":[0],"mappings":";AAIA,MAAa,MAAM;AACnB,MAAa,MAAM;AACnB,MAAa,YAAY;AACzB,MAAa,kBAAkB;AAC/B,MAAa,QAAQ;AACrB,MAAa,cAAc;AAC3B,MAAa,eAAe;AAC5B,MAAa,QAAQ;AACrB,MAAa,UAAU;AACvB,MAAa,YAAY;AACzB,MAAa,eAAe;AAC5B,MAAa,WAAW;AACxB,MAAa,OAAO;AACpB,MAAa,QAAQ;AACrB,MAAa,QAAQ;AACrB,MAAa,MAAM;AACnB,MAAa,QAAQ;AACrB,MAAa,eAAe;AAC5B,MAAa,eAAe;AAC5B,MAAa,WAAW;AACxB,MAAa,gBAAgB;AAC7B,MAAa,sBAAsB;AACnC,MAAa,YAAY;AACzB,MAAa,uBAAuB;AACpC,MAAa,eAAe;AAC5B,MAAa,qBAAqB;AAClC,MAAa,gBAAgB;AAC7B,MAAa,sBAAsB;AACnC,SAAgB,MAAM,GAAG;AACvB,QAAO,MAAM,aAAa,MAAM;;AAElC,SAAgB,aAAa,GAAG;AAC9B,QAAO,MAAM,OAAO,MAAM;;AAE5B,SAAgB,kBAAkB,GAAG;AACnC,QAAO,aAAa,EAAE,IAAI,MAAM,EAAE;;AAEpC,SAAgB,gBAAgB,GAAG;AACjC,QAAO,MAAM,SAAS,MAAM,uBAAuB,MAAM,wBAAwB,MAAM,sBAAsB,MAAM"}
|