gray-matter-es 0.1.3 → 0.2.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/README.md +69 -11
- package/dist/index.d.mts +37 -17
- package/dist/index.mjs +32 -35
- package/package.json +1 -1
- package/src/index.ts +69 -97
- package/src/types.ts +0 -16
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ ESM-only [gray-matter](https://github.com/jonschlinkert/gray-matter) implementat
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
- 🚀 ESM-only, no CommonJS
|
|
11
|
+
- 🌲 Tree-shakable (named exports)
|
|
11
12
|
- 🌐 Browser-compatible (no Node.js dependencies)
|
|
12
13
|
- 📦 Zero runtime dependencies (YAML parser bundled from [@std/yaml](https://jsr.io/@std/yaml))
|
|
13
14
|
- 🔷 Full TypeScript support with strict types
|
|
@@ -24,12 +25,10 @@ pnpm add gray-matter-es
|
|
|
24
25
|
## Usage
|
|
25
26
|
|
|
26
27
|
```typescript
|
|
27
|
-
import matter from "gray-matter-es";
|
|
28
|
-
// or
|
|
29
|
-
import { matter } from "gray-matter-es";
|
|
28
|
+
import * as matter from "gray-matter-es";
|
|
30
29
|
|
|
31
30
|
// Parse front matter
|
|
32
|
-
const file = matter("---\ntitle: Hello\n---\nThis is content");
|
|
31
|
+
const file = matter.matter("---\ntitle: Hello\n---\nThis is content");
|
|
33
32
|
console.log(file.data); // { title: 'Hello' }
|
|
34
33
|
console.log(file.content); // 'This is content'
|
|
35
34
|
|
|
@@ -47,6 +46,12 @@ matter.test("---\ntitle: Hello\n---"); // true
|
|
|
47
46
|
matter.language("---json\n{}\n---"); // { raw: 'json', name: 'json' }
|
|
48
47
|
```
|
|
49
48
|
|
|
49
|
+
You can also import individual functions for tree-shaking:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { matter, stringify, test, language, clearCache, cache } from "gray-matter-es";
|
|
53
|
+
```
|
|
54
|
+
|
|
50
55
|
### Custom Delimiters
|
|
51
56
|
|
|
52
57
|
```typescript
|
|
@@ -94,18 +99,26 @@ Parse front matter from a string or Uint8Array.
|
|
|
94
99
|
- `isEmpty` - True if front matter block was empty
|
|
95
100
|
- `stringify(data?, options?)` - Stringify the file back
|
|
96
101
|
|
|
97
|
-
### `
|
|
102
|
+
### `stringify(file, data?, options?)`
|
|
98
103
|
|
|
99
104
|
Stringify data to front matter and append content.
|
|
100
105
|
|
|
101
|
-
### `
|
|
106
|
+
### `test(str, options?)`
|
|
102
107
|
|
|
103
108
|
Test if a string has front matter.
|
|
104
109
|
|
|
105
|
-
### `
|
|
110
|
+
### `language(str, options?)`
|
|
106
111
|
|
|
107
112
|
Detect the language specified after the opening delimiter.
|
|
108
113
|
|
|
114
|
+
### `clearCache()`
|
|
115
|
+
|
|
116
|
+
Clear the internal cache.
|
|
117
|
+
|
|
118
|
+
### `cache`
|
|
119
|
+
|
|
120
|
+
The internal cache (read-only access).
|
|
121
|
+
|
|
109
122
|
### Options
|
|
110
123
|
|
|
111
124
|
- `language` - Language to use for parsing (default: `'yaml'`)
|
|
@@ -131,9 +144,25 @@ Detect the language specified after the opening delimiter.
|
|
|
131
144
|
|
|
132
145
|
```diff
|
|
133
146
|
- const matter = require('gray-matter');
|
|
134
|
-
+ import matter from 'gray-matter-es';
|
|
135
|
-
|
|
136
|
-
|
|
147
|
+
+ import * as matter from 'gray-matter-es';
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### API Changes
|
|
151
|
+
|
|
152
|
+
The main function is now `matter.matter()` instead of `matter()`:
|
|
153
|
+
|
|
154
|
+
```diff
|
|
155
|
+
- const result = matter(str);
|
|
156
|
+
+ const result = matter.matter(str);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Other methods remain the same:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
matter.stringify(file, data);
|
|
163
|
+
matter.test(str);
|
|
164
|
+
matter.language(str);
|
|
165
|
+
matter.clearCache();
|
|
137
166
|
```
|
|
138
167
|
|
|
139
168
|
### Removed Features
|
|
@@ -187,7 +216,36 @@ If you're using CommonJS, you'll need to either:
|
|
|
187
216
|
2. Use dynamic import:
|
|
188
217
|
|
|
189
218
|
```javascript
|
|
190
|
-
const matter = await import("gray-matter-es")
|
|
219
|
+
const { matter } = await import("gray-matter-es");
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Development
|
|
223
|
+
|
|
224
|
+
### Prerequisites
|
|
225
|
+
|
|
226
|
+
This project uses [Nix](https://nixos.org/) for development environment management. Make sure you have Nix installed with flakes enabled.
|
|
227
|
+
|
|
228
|
+
### Setup
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Enter the development shell
|
|
232
|
+
nix develop
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Commands
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# Run tests
|
|
239
|
+
pnpm run test
|
|
240
|
+
|
|
241
|
+
# Type check with tsgo
|
|
242
|
+
pnpm run typecheck
|
|
243
|
+
|
|
244
|
+
# Build
|
|
245
|
+
pnpm run build
|
|
246
|
+
|
|
247
|
+
# Lint
|
|
248
|
+
pnpm run lint
|
|
191
249
|
```
|
|
192
250
|
|
|
193
251
|
## License
|
package/dist/index.d.mts
CHANGED
|
@@ -63,20 +63,6 @@ type GrayMatterInput = string | Uint8Array | {
|
|
|
63
63
|
content: string;
|
|
64
64
|
data?: Record<string, unknown>;
|
|
65
65
|
};
|
|
66
|
-
/**
|
|
67
|
-
* The matter function interface with static methods
|
|
68
|
-
*/
|
|
69
|
-
interface MatterFunction {
|
|
70
|
-
(input: GrayMatterInput, options?: GrayMatterOptions): GrayMatterFile;
|
|
71
|
-
stringify: (file: GrayMatterFile | string, data?: Record<string, unknown>, options?: GrayMatterOptions) => string;
|
|
72
|
-
test: (str: string, options?: GrayMatterOptions) => boolean;
|
|
73
|
-
language: (str: string, options?: GrayMatterOptions) => {
|
|
74
|
-
raw: string;
|
|
75
|
-
name: string;
|
|
76
|
-
};
|
|
77
|
-
clearCache: () => void;
|
|
78
|
-
cache: Map<string, GrayMatterFile>;
|
|
79
|
-
}
|
|
80
66
|
//#endregion
|
|
81
67
|
//#region src/engines.d.ts
|
|
82
68
|
/**
|
|
@@ -86,8 +72,42 @@ type BuiltinLanguage = "yaml" | "json";
|
|
|
86
72
|
//#endregion
|
|
87
73
|
//#region src/index.d.ts
|
|
88
74
|
/**
|
|
89
|
-
*
|
|
75
|
+
* Cache for parsed results
|
|
76
|
+
*/
|
|
77
|
+
declare const cache: Map<string, GrayMatterFile>;
|
|
78
|
+
/**
|
|
79
|
+
* Takes a string or object with `content` property, extracts
|
|
80
|
+
* and parses front-matter from the string, then returns an object
|
|
81
|
+
* with `data`, `content` and other useful properties.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { matter } from 'gray-matter-es';
|
|
86
|
+
* console.log(matter('---\ntitle: Home\n---\nOther stuff'));
|
|
87
|
+
* //=> { data: { title: 'Home'}, content: 'Other stuff' }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
declare function matter(input: GrayMatterInput, options?: GrayMatterOptions): GrayMatterFile;
|
|
91
|
+
/**
|
|
92
|
+
* Clear the cache
|
|
93
|
+
*/
|
|
94
|
+
declare function clearCache(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Detect the language to use, if one is defined after the
|
|
97
|
+
* first front-matter delimiter.
|
|
98
|
+
*/
|
|
99
|
+
declare function language(str: string, options?: GrayMatterOptions): {
|
|
100
|
+
raw: string;
|
|
101
|
+
name: string;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Returns true if the given string has front matter.
|
|
105
|
+
*/
|
|
106
|
+
declare function test(str: string, options?: GrayMatterOptions): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Stringify an object to YAML or the specified language, and
|
|
109
|
+
* append it to the given string.
|
|
90
110
|
*/
|
|
91
|
-
declare
|
|
111
|
+
declare function stringify(file: GrayMatterFile | string, data?: Record<string, unknown>, options?: GrayMatterOptions): string;
|
|
92
112
|
//#endregion
|
|
93
|
-
export { type BuiltinLanguage, type Engine, type GrayMatterFile, type GrayMatterInput, type GrayMatterOptions, type
|
|
113
|
+
export { type BuiltinLanguage, type Engine, type GrayMatterFile, type GrayMatterInput, type GrayMatterOptions, type ResolvedOptions, cache, clearCache, language, matter, stringify, test };
|
package/dist/index.mjs
CHANGED
|
@@ -2103,7 +2103,7 @@ var DumperState = class {
|
|
|
2103
2103
|
* @param data The data to serialize.
|
|
2104
2104
|
* @param options The options for serialization.
|
|
2105
2105
|
* @returns A YAML string.
|
|
2106
|
-
*/ function stringify$
|
|
2106
|
+
*/ function stringify$2(data, options = {}) {
|
|
2107
2107
|
return new DumperState({
|
|
2108
2108
|
...options,
|
|
2109
2109
|
schema: SCHEMA_MAP.get(options.schema)
|
|
@@ -2136,7 +2136,7 @@ const yaml = {
|
|
|
2136
2136
|
return toRecord(parse$1(str$1));
|
|
2137
2137
|
},
|
|
2138
2138
|
stringify: (data) => {
|
|
2139
|
-
return stringify$
|
|
2139
|
+
return stringify$2(data);
|
|
2140
2140
|
}
|
|
2141
2141
|
};
|
|
2142
2142
|
/**
|
|
@@ -2158,11 +2158,11 @@ const json = {
|
|
|
2158
2158
|
/**
|
|
2159
2159
|
* Get engine by language name
|
|
2160
2160
|
*/
|
|
2161
|
-
function getEngine(language) {
|
|
2162
|
-
switch (language) {
|
|
2161
|
+
function getEngine(language$1) {
|
|
2162
|
+
switch (language$1) {
|
|
2163
2163
|
case "yaml": return yaml;
|
|
2164
2164
|
case "json": return json;
|
|
2165
|
-
default: throw new Error(`Unknown language: ${language}`);
|
|
2165
|
+
default: throw new Error(`Unknown language: ${language$1}`);
|
|
2166
2166
|
}
|
|
2167
2167
|
}
|
|
2168
2168
|
|
|
@@ -2192,8 +2192,8 @@ function excerpt(file, options) {
|
|
|
2192
2192
|
/**
|
|
2193
2193
|
* Parse front matter string using the specified language engine
|
|
2194
2194
|
*/
|
|
2195
|
-
function parse(language, str$1) {
|
|
2196
|
-
return getEngine(language).parse(str$1);
|
|
2195
|
+
function parse(language$1, str$1) {
|
|
2196
|
+
return getEngine(language$1).parse(str$1);
|
|
2197
2197
|
}
|
|
2198
2198
|
|
|
2199
2199
|
//#endregion
|
|
@@ -2213,7 +2213,7 @@ function newline(str$1) {
|
|
|
2213
2213
|
/**
|
|
2214
2214
|
* Stringify file object to string with front matter
|
|
2215
2215
|
*/
|
|
2216
|
-
function stringify(file, data, options) {
|
|
2216
|
+
function stringify$1(file, data, options) {
|
|
2217
2217
|
if (data == null && options == null) if (isGrayMatterFile(file)) {
|
|
2218
2218
|
data = file.data;
|
|
2219
2219
|
options = {};
|
|
@@ -2264,19 +2264,19 @@ function toFile(input) {
|
|
|
2264
2264
|
const normalized = normalizeInput(input);
|
|
2265
2265
|
const data = isObject$1(normalized.data) ? normalized.data : {};
|
|
2266
2266
|
const content = toString(normalized.content ?? "");
|
|
2267
|
-
const language = normalized.language ?? "";
|
|
2267
|
+
const language$1 = normalized.language ?? "";
|
|
2268
2268
|
const matter$1 = normalized.matter ?? "";
|
|
2269
2269
|
return {
|
|
2270
2270
|
data,
|
|
2271
2271
|
content,
|
|
2272
2272
|
excerpt: "",
|
|
2273
2273
|
orig: toUint8Array(normalized.content ?? ""),
|
|
2274
|
-
language,
|
|
2274
|
+
language: language$1,
|
|
2275
2275
|
matter: matter$1,
|
|
2276
2276
|
isEmpty: false,
|
|
2277
2277
|
stringify(newData, options) {
|
|
2278
2278
|
if (options?.language) this.language = options.language;
|
|
2279
|
-
return stringify(this, newData, options);
|
|
2279
|
+
return stringify$1(this, newData, options);
|
|
2280
2280
|
}
|
|
2281
2281
|
};
|
|
2282
2282
|
}
|
|
@@ -2294,12 +2294,12 @@ const cache = /* @__PURE__ */ new Map();
|
|
|
2294
2294
|
*
|
|
2295
2295
|
* @example
|
|
2296
2296
|
* ```ts
|
|
2297
|
-
* import matter from 'gray-matter-es';
|
|
2297
|
+
* import { matter } from 'gray-matter-es';
|
|
2298
2298
|
* console.log(matter('---\ntitle: Home\n---\nOther stuff'));
|
|
2299
2299
|
* //=> { data: { title: 'Home'}, content: 'Other stuff' }
|
|
2300
2300
|
* ```
|
|
2301
2301
|
*/
|
|
2302
|
-
function
|
|
2302
|
+
function matter(input, options) {
|
|
2303
2303
|
if (input === "") return {
|
|
2304
2304
|
...toFile(input),
|
|
2305
2305
|
isEmpty: true
|
|
@@ -2317,6 +2317,12 @@ function matterImpl(input, options) {
|
|
|
2317
2317
|
return parseMatter(file, options);
|
|
2318
2318
|
}
|
|
2319
2319
|
/**
|
|
2320
|
+
* Clear the cache
|
|
2321
|
+
*/
|
|
2322
|
+
function clearCache() {
|
|
2323
|
+
cache.clear();
|
|
2324
|
+
}
|
|
2325
|
+
/**
|
|
2320
2326
|
* Parse front matter from file
|
|
2321
2327
|
*/
|
|
2322
2328
|
function parseMatter(file, options) {
|
|
@@ -2333,7 +2339,7 @@ function parseMatter(file, options) {
|
|
|
2333
2339
|
if (str$1.at(openLen) === open.at(-1)) return file;
|
|
2334
2340
|
str$1 = str$1.slice(openLen);
|
|
2335
2341
|
const len = str$1.length;
|
|
2336
|
-
const lang =
|
|
2342
|
+
const lang = language(str$1, opts);
|
|
2337
2343
|
if (lang.name) {
|
|
2338
2344
|
file.language = lang.name;
|
|
2339
2345
|
str$1 = str$1.slice(lang.raw.length);
|
|
@@ -2359,38 +2365,29 @@ function parseMatter(file, options) {
|
|
|
2359
2365
|
* Detect the language to use, if one is defined after the
|
|
2360
2366
|
* first front-matter delimiter.
|
|
2361
2367
|
*/
|
|
2362
|
-
function
|
|
2368
|
+
function language(str$1, options) {
|
|
2363
2369
|
const opts = defaults(options);
|
|
2364
2370
|
const open = opts.delimiters[0];
|
|
2365
|
-
if (
|
|
2366
|
-
const
|
|
2371
|
+
if (test(str$1, opts)) str$1 = str$1.slice(open.length);
|
|
2372
|
+
const lang = str$1.slice(0, str$1.search(/\r?\n/));
|
|
2367
2373
|
return {
|
|
2368
|
-
raw:
|
|
2369
|
-
name:
|
|
2374
|
+
raw: lang,
|
|
2375
|
+
name: lang ? lang.trim() : ""
|
|
2370
2376
|
};
|
|
2371
2377
|
}
|
|
2372
2378
|
/**
|
|
2373
2379
|
* Returns true if the given string has front matter.
|
|
2374
2380
|
*/
|
|
2375
|
-
function
|
|
2381
|
+
function test(str$1, options) {
|
|
2376
2382
|
return str$1.startsWith(defaults(options).delimiters[0]);
|
|
2377
2383
|
}
|
|
2378
2384
|
/**
|
|
2379
|
-
*
|
|
2385
|
+
* Stringify an object to YAML or the specified language, and
|
|
2386
|
+
* append it to the given string.
|
|
2380
2387
|
*/
|
|
2381
|
-
|
|
2382
|
-
stringify
|
|
2383
|
-
|
|
2384
|
-
return stringify(file, data, options);
|
|
2385
|
-
},
|
|
2386
|
-
test: matterTest,
|
|
2387
|
-
language: matterLanguage,
|
|
2388
|
-
clearCache: () => {
|
|
2389
|
-
cache.clear();
|
|
2390
|
-
},
|
|
2391
|
-
cache
|
|
2392
|
-
});
|
|
2393
|
-
var src_default = matter;
|
|
2388
|
+
function stringify(file, data, options) {
|
|
2389
|
+
return stringify$1(typeof file === "string" ? matter(file, options) : file, data, options);
|
|
2390
|
+
}
|
|
2394
2391
|
|
|
2395
2392
|
//#endregion
|
|
2396
|
-
export {
|
|
2393
|
+
export { cache, clearCache, language, matter, stringify, test };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -2,21 +2,15 @@ import { defaults } from "./defaults.ts";
|
|
|
2
2
|
import { toBuiltinLanguage } from "./engines.ts";
|
|
3
3
|
import { excerpt } from "./excerpt.ts";
|
|
4
4
|
import { parse } from "./parse.ts";
|
|
5
|
-
import { stringify } from "./stringify.ts";
|
|
5
|
+
import { stringify as stringifyImpl } from "./stringify.ts";
|
|
6
6
|
import { toFile } from "./to-file.ts";
|
|
7
|
-
import type {
|
|
8
|
-
GrayMatterFile,
|
|
9
|
-
GrayMatterInput,
|
|
10
|
-
GrayMatterOptions,
|
|
11
|
-
MatterFunction,
|
|
12
|
-
} from "./types.ts";
|
|
7
|
+
import type { GrayMatterFile, GrayMatterInput, GrayMatterOptions } from "./types.ts";
|
|
13
8
|
|
|
14
9
|
export type {
|
|
15
10
|
Engine,
|
|
16
11
|
GrayMatterFile,
|
|
17
12
|
GrayMatterInput,
|
|
18
13
|
GrayMatterOptions,
|
|
19
|
-
MatterFunction,
|
|
20
14
|
ResolvedOptions,
|
|
21
15
|
} from "./types.ts";
|
|
22
16
|
|
|
@@ -25,7 +19,7 @@ export type { BuiltinLanguage } from "./engines.ts";
|
|
|
25
19
|
/**
|
|
26
20
|
* Cache for parsed results
|
|
27
21
|
*/
|
|
28
|
-
const cache = new Map<string, GrayMatterFile>();
|
|
22
|
+
const cache: Map<string, GrayMatterFile> = new Map<string, GrayMatterFile>();
|
|
29
23
|
|
|
30
24
|
/**
|
|
31
25
|
* Takes a string or object with `content` property, extracts
|
|
@@ -34,12 +28,12 @@ const cache = new Map<string, GrayMatterFile>();
|
|
|
34
28
|
*
|
|
35
29
|
* @example
|
|
36
30
|
* ```ts
|
|
37
|
-
* import matter from 'gray-matter-es';
|
|
31
|
+
* import { matter } from 'gray-matter-es';
|
|
38
32
|
* console.log(matter('---\ntitle: Home\n---\nOther stuff'));
|
|
39
33
|
* //=> { data: { title: 'Home'}, content: 'Other stuff' }
|
|
40
34
|
* ```
|
|
41
35
|
*/
|
|
42
|
-
function
|
|
36
|
+
function matter(input: GrayMatterInput, options?: GrayMatterOptions): GrayMatterFile {
|
|
43
37
|
if (input === "") {
|
|
44
38
|
return { ...toFile(input), isEmpty: true };
|
|
45
39
|
}
|
|
@@ -61,6 +55,13 @@ function matterImpl(input: GrayMatterInput, options?: GrayMatterOptions): GrayMa
|
|
|
61
55
|
return parseMatter(file, options);
|
|
62
56
|
}
|
|
63
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Clear the cache
|
|
60
|
+
*/
|
|
61
|
+
function clearCache(): void {
|
|
62
|
+
cache.clear();
|
|
63
|
+
}
|
|
64
|
+
|
|
64
65
|
/**
|
|
65
66
|
* Parse front matter from file
|
|
66
67
|
*/
|
|
@@ -93,7 +94,7 @@ function parseMatter(file: GrayMatterFile, options?: GrayMatterOptions): GrayMat
|
|
|
93
94
|
const len = str.length;
|
|
94
95
|
|
|
95
96
|
// use the language defined after first delimiter, if it exists
|
|
96
|
-
const lang =
|
|
97
|
+
const lang = language(str, opts);
|
|
97
98
|
if (lang.name) {
|
|
98
99
|
file.language = lang.name;
|
|
99
100
|
str = str.slice(lang.raw.length);
|
|
@@ -139,78 +140,49 @@ function parseMatter(file: GrayMatterFile, options?: GrayMatterOptions): GrayMat
|
|
|
139
140
|
* Detect the language to use, if one is defined after the
|
|
140
141
|
* first front-matter delimiter.
|
|
141
142
|
*/
|
|
142
|
-
function
|
|
143
|
+
function language(str: string, options?: GrayMatterOptions): { raw: string; name: string } {
|
|
143
144
|
const opts = defaults(options);
|
|
144
145
|
const open = opts.delimiters[0];
|
|
145
146
|
|
|
146
|
-
if (
|
|
147
|
+
if (test(str, opts)) {
|
|
147
148
|
str = str.slice(open.length);
|
|
148
149
|
}
|
|
149
150
|
|
|
150
|
-
const
|
|
151
|
+
const lang = str.slice(0, str.search(/\r?\n/));
|
|
151
152
|
return {
|
|
152
|
-
raw:
|
|
153
|
-
name:
|
|
153
|
+
raw: lang,
|
|
154
|
+
name: lang ? lang.trim() : "",
|
|
154
155
|
};
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
/**
|
|
158
159
|
* Returns true if the given string has front matter.
|
|
159
160
|
*/
|
|
160
|
-
function
|
|
161
|
+
function test(str: string, options?: GrayMatterOptions): boolean {
|
|
161
162
|
return str.startsWith(defaults(options).delimiters[0]);
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
/**
|
|
165
|
-
*
|
|
166
|
+
* Stringify an object to YAML or the specified language, and
|
|
167
|
+
* append it to the given string.
|
|
166
168
|
*/
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (typeof file === "string") file = matterImpl(file, options);
|
|
178
|
-
return stringify(file, data, options);
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Returns true if the given string has front matter.
|
|
183
|
-
*/
|
|
184
|
-
test: matterTest,
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Detect the language to use, if one is defined after the
|
|
188
|
-
* first front-matter delimiter.
|
|
189
|
-
*/
|
|
190
|
-
language: matterLanguage,
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Clear the cache
|
|
194
|
-
*/
|
|
195
|
-
clearCache: (): void => {
|
|
196
|
-
cache.clear();
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Expose cache (read-only access)
|
|
201
|
-
*/
|
|
202
|
-
cache,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
export { matter };
|
|
206
|
-
export default matter;
|
|
169
|
+
function stringify(
|
|
170
|
+
file: GrayMatterFile | string,
|
|
171
|
+
data?: Record<string, unknown>,
|
|
172
|
+
options?: GrayMatterOptions,
|
|
173
|
+
): string {
|
|
174
|
+
const resolvedFile = typeof file === "string" ? matter(file, options) : file;
|
|
175
|
+
return stringifyImpl(resolvedFile, data, options);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export { matter, stringify, test, language, clearCache, cache };
|
|
207
179
|
|
|
208
180
|
if (import.meta.vitest) {
|
|
209
|
-
const { fc, test } = await import("@fast-check/vitest");
|
|
181
|
+
const { fc, test: fcTest } = await import("@fast-check/vitest");
|
|
210
182
|
|
|
211
183
|
describe("matter", () => {
|
|
212
184
|
beforeEach(() => {
|
|
213
|
-
|
|
185
|
+
clearCache();
|
|
214
186
|
});
|
|
215
187
|
|
|
216
188
|
it("should extract YAML front matter", () => {
|
|
@@ -286,9 +258,9 @@ if (import.meta.vitest) {
|
|
|
286
258
|
});
|
|
287
259
|
});
|
|
288
260
|
|
|
289
|
-
describe("
|
|
261
|
+
describe("stringify", () => {
|
|
290
262
|
it("should stringify data to YAML front matter", () => {
|
|
291
|
-
const result =
|
|
263
|
+
const result = stringify("content", { title: "Hello" });
|
|
292
264
|
expect(result).toContain("---");
|
|
293
265
|
expect(result).toContain("title: Hello");
|
|
294
266
|
expect(result).toContain("content");
|
|
@@ -296,36 +268,36 @@ if (import.meta.vitest) {
|
|
|
296
268
|
|
|
297
269
|
it("should stringify file object", () => {
|
|
298
270
|
const file = matter("---\ntitle: Test\n---\ncontent");
|
|
299
|
-
const result =
|
|
271
|
+
const result = stringify(file, { title: "Updated" });
|
|
300
272
|
expect(result).toContain("title: Updated");
|
|
301
273
|
});
|
|
302
274
|
});
|
|
303
275
|
|
|
304
|
-
describe("
|
|
276
|
+
describe("test", () => {
|
|
305
277
|
it("should return true for string with front matter", () => {
|
|
306
|
-
expect(
|
|
278
|
+
expect(test("---\nabc: xyz\n---")).toBe(true);
|
|
307
279
|
});
|
|
308
280
|
|
|
309
281
|
it("should return false for string without front matter", () => {
|
|
310
|
-
expect(
|
|
282
|
+
expect(test("foo bar")).toBe(false);
|
|
311
283
|
});
|
|
312
284
|
});
|
|
313
285
|
|
|
314
|
-
describe("
|
|
286
|
+
describe("language", () => {
|
|
315
287
|
it("should detect language after delimiter", () => {
|
|
316
|
-
const result =
|
|
288
|
+
const result = language("---json\n{}\n---");
|
|
317
289
|
expect(result.name).toBe("json");
|
|
318
290
|
});
|
|
319
291
|
|
|
320
292
|
it("should return empty for no language", () => {
|
|
321
|
-
const result =
|
|
293
|
+
const result = language("---\nabc: xyz\n---");
|
|
322
294
|
expect(result.name).toBe("");
|
|
323
295
|
});
|
|
324
296
|
});
|
|
325
297
|
|
|
326
298
|
describe("property-based tests", () => {
|
|
327
299
|
beforeEach(() => {
|
|
328
|
-
|
|
300
|
+
clearCache();
|
|
329
301
|
});
|
|
330
302
|
|
|
331
303
|
/** Arbitrary for YAML-safe keys */
|
|
@@ -343,12 +315,12 @@ if (import.meta.vitest) {
|
|
|
343
315
|
/** Arbitrary for simple YAML-compatible objects */
|
|
344
316
|
const yamlSafeObject = fc.dictionary(yamlKey, yamlSafeValue, { minKeys: 1, maxKeys: 5 });
|
|
345
317
|
|
|
346
|
-
|
|
318
|
+
fcTest.prop([fc.string({ minLength: 1, maxLength: 100 })])(
|
|
347
319
|
"Uint8Array and string input should produce equivalent results",
|
|
348
320
|
(content) => {
|
|
349
|
-
|
|
321
|
+
clearCache();
|
|
350
322
|
const fromString = matter(content);
|
|
351
|
-
|
|
323
|
+
clearCache();
|
|
352
324
|
const fromUint8Array = matter(new TextEncoder().encode(content));
|
|
353
325
|
|
|
354
326
|
expect(fromString.content).toBe(fromUint8Array.content);
|
|
@@ -357,7 +329,7 @@ if (import.meta.vitest) {
|
|
|
357
329
|
},
|
|
358
330
|
);
|
|
359
331
|
|
|
360
|
-
|
|
332
|
+
fcTest.prop([yamlSafeObject, fc.string({ minLength: 0, maxLength: 50 })])(
|
|
361
333
|
"parse then stringify should preserve data",
|
|
362
334
|
(data, content) => {
|
|
363
335
|
const frontMatter = Object.entries(data)
|
|
@@ -365,21 +337,21 @@ if (import.meta.vitest) {
|
|
|
365
337
|
.join("\n");
|
|
366
338
|
const input = `---\n${frontMatter}\n---\n${content}`;
|
|
367
339
|
|
|
368
|
-
|
|
340
|
+
clearCache();
|
|
369
341
|
const parsed = matter(input);
|
|
370
|
-
const stringified =
|
|
371
|
-
|
|
342
|
+
const stringified = stringify(parsed);
|
|
343
|
+
clearCache();
|
|
372
344
|
const reparsed = matter(stringified);
|
|
373
345
|
|
|
374
346
|
expect(reparsed.data).toEqual(parsed.data);
|
|
375
347
|
},
|
|
376
348
|
);
|
|
377
349
|
|
|
378
|
-
|
|
350
|
+
fcTest.prop([fc.string({ minLength: 0, maxLength: 100 })])(
|
|
379
351
|
"content without front matter should be preserved",
|
|
380
352
|
(content) => {
|
|
381
353
|
const safeContent = content.replace(/^---/gm, "___");
|
|
382
|
-
|
|
354
|
+
clearCache();
|
|
383
355
|
const result = matter(safeContent);
|
|
384
356
|
|
|
385
357
|
expect(result.content).toBe(safeContent);
|
|
@@ -387,26 +359,26 @@ if (import.meta.vitest) {
|
|
|
387
359
|
},
|
|
388
360
|
);
|
|
389
361
|
|
|
390
|
-
|
|
362
|
+
fcTest.prop([
|
|
391
363
|
yamlSafeObject,
|
|
392
364
|
fc.string({ minLength: 0, maxLength: 50 }),
|
|
393
365
|
fc.string({ minLength: 1, maxLength: 50 }),
|
|
394
|
-
])("
|
|
366
|
+
])("test should correctly detect front matter", (data, content, noFrontMatter) => {
|
|
395
367
|
const frontMatter = Object.entries(data)
|
|
396
368
|
.map(([k, v]) => `${k}: ${typeof v === "string" ? JSON.stringify(v) : v}`)
|
|
397
369
|
.join("\n");
|
|
398
370
|
const withFrontMatter = `---\n${frontMatter}\n---\n${content}`;
|
|
399
371
|
const withoutFrontMatter = noFrontMatter.replace(/^---/gm, "___");
|
|
400
372
|
|
|
401
|
-
expect(
|
|
402
|
-
expect(
|
|
373
|
+
expect(test(withFrontMatter)).toBe(true);
|
|
374
|
+
expect(test(withoutFrontMatter)).toBe(withoutFrontMatter.startsWith("---"));
|
|
403
375
|
});
|
|
404
376
|
|
|
405
|
-
|
|
377
|
+
fcTest.prop([fc.constantFrom("yaml", "json"), yamlSafeObject, fc.string({ maxLength: 30 })])(
|
|
406
378
|
"should handle different languages",
|
|
407
|
-
(
|
|
379
|
+
(lang, data, content) => {
|
|
408
380
|
let frontMatterContent: string;
|
|
409
|
-
if (
|
|
381
|
+
if (lang === "json") {
|
|
410
382
|
frontMatterContent = JSON.stringify(data);
|
|
411
383
|
} else {
|
|
412
384
|
frontMatterContent = Object.entries(data)
|
|
@@ -414,20 +386,20 @@ if (import.meta.vitest) {
|
|
|
414
386
|
.join("\n");
|
|
415
387
|
}
|
|
416
388
|
|
|
417
|
-
const input = `---${
|
|
418
|
-
|
|
389
|
+
const input = `---${lang}\n${frontMatterContent}\n---\n${content}`;
|
|
390
|
+
clearCache();
|
|
419
391
|
const result = matter(input);
|
|
420
392
|
|
|
421
|
-
expect(result.language).toBe(
|
|
393
|
+
expect(result.language).toBe(lang);
|
|
422
394
|
expect(result.data).toEqual(data);
|
|
423
395
|
},
|
|
424
396
|
);
|
|
425
397
|
|
|
426
|
-
|
|
398
|
+
fcTest.prop([fc.constantFrom("---", "~~~", "***", "+++")])(
|
|
427
399
|
"should handle custom delimiters",
|
|
428
400
|
(delimiter) => {
|
|
429
401
|
const input = `${delimiter}\ntitle: Test\n${delimiter}\ncontent`;
|
|
430
|
-
|
|
402
|
+
clearCache();
|
|
431
403
|
const result = matter(input, { delimiters: delimiter });
|
|
432
404
|
|
|
433
405
|
expect(result.data).toEqual({ title: "Test" });
|
|
@@ -435,7 +407,7 @@ if (import.meta.vitest) {
|
|
|
435
407
|
},
|
|
436
408
|
);
|
|
437
409
|
|
|
438
|
-
|
|
410
|
+
fcTest.prop([
|
|
439
411
|
fc.string({ minLength: 1, maxLength: 20 }),
|
|
440
412
|
fc.string({ minLength: 1, maxLength: 20 }),
|
|
441
413
|
])("should extract excerpt with custom separator", (excerptText, contentText) => {
|
|
@@ -444,22 +416,22 @@ if (import.meta.vitest) {
|
|
|
444
416
|
const safeContent = contentText.replace(separator, "");
|
|
445
417
|
const input = `---\ntitle: Test\n---\n${safeExcerpt}\n${separator}\n${safeContent}`;
|
|
446
418
|
|
|
447
|
-
|
|
419
|
+
clearCache();
|
|
448
420
|
const result = matter(input, { excerpt: true, excerpt_separator: separator });
|
|
449
421
|
|
|
450
422
|
expect(result.excerpt).toBe(`${safeExcerpt}\n`);
|
|
451
423
|
});
|
|
452
424
|
|
|
453
|
-
|
|
425
|
+
fcTest.prop([fc.string({ minLength: 0, maxLength: 50 })])(
|
|
454
426
|
"should handle CRLF and LF consistently",
|
|
455
427
|
(content) => {
|
|
456
428
|
const yamlData = "title: Test";
|
|
457
429
|
const inputLF = `---\n${yamlData}\n---\n${content}`;
|
|
458
430
|
const inputCRLF = `---\r\n${yamlData}\r\n---\r\n${content}`;
|
|
459
431
|
|
|
460
|
-
|
|
432
|
+
clearCache();
|
|
461
433
|
const resultLF = matter(inputLF);
|
|
462
|
-
|
|
434
|
+
clearCache();
|
|
463
435
|
const resultCRLF = matter(inputCRLF);
|
|
464
436
|
|
|
465
437
|
expect(resultLF.data).toEqual(resultCRLF.data);
|
package/src/types.ts
CHANGED
|
@@ -66,19 +66,3 @@ export type GrayMatterInput =
|
|
|
66
66
|
| string
|
|
67
67
|
| Uint8Array
|
|
68
68
|
| { content: string; data?: Record<string, unknown> };
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The matter function interface with static methods
|
|
72
|
-
*/
|
|
73
|
-
export interface MatterFunction {
|
|
74
|
-
(input: GrayMatterInput, options?: GrayMatterOptions): GrayMatterFile;
|
|
75
|
-
stringify: (
|
|
76
|
-
file: GrayMatterFile | string,
|
|
77
|
-
data?: Record<string, unknown>,
|
|
78
|
-
options?: GrayMatterOptions,
|
|
79
|
-
) => string;
|
|
80
|
-
test: (str: string, options?: GrayMatterOptions) => boolean;
|
|
81
|
-
language: (str: string, options?: GrayMatterOptions) => { raw: string; name: string };
|
|
82
|
-
clearCache: () => void;
|
|
83
|
-
cache: Map<string, GrayMatterFile>;
|
|
84
|
-
}
|