-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfrontmatter.ts
More file actions
86 lines (69 loc) · 2.53 KB
/
Copy pathfrontmatter.ts
File metadata and controls
86 lines (69 loc) · 2.53 KB
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
import matter from 'gray-matter';
import { PageMeta, ParseResult } from '../models/types';
const VALID_TYPES = ['entity', 'concept', 'source'] as const;
export function parseFrontmatter(filePath: string, rawContent: string): ParseResult {
let parsed: matter.GrayMatterFile<string>;
try {
parsed = matter(rawContent);
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
return { success: false, error: `Failed to parse frontmatter: ${message}` };
}
const data = parsed.data;
if (!data || Object.keys(data).length === 0) {
return { success: false, error: 'Frontmatter is missing or empty' };
}
if (typeof data.title !== 'string' || data.title.trim() === '') {
return { success: false, error: 'Required field "title" is missing or not a non-empty string' };
}
if (!VALID_TYPES.includes(data.type)) {
return {
success: false,
error: `Field "type" must be one of: ${VALID_TYPES.join(', ')}. Got: "${data.type}"`,
};
}
if (!Array.isArray(data.tags)) {
return { success: false, error: 'Field "tags" must be an array' };
}
for (const tag of data.tags) {
if (typeof tag !== 'string') {
return { success: false, error: 'Field "tags" must be an array of strings' };
}
}
if (typeof data.created !== 'string' && !(data.created instanceof Date)) {
return { success: false, error: 'Required field "created" is missing or not a string' };
}
if (typeof data.updated !== 'string' && !(data.updated instanceof Date)) {
return { success: false, error: 'Required field "updated" is missing or not a string' };
}
const created = data.created instanceof Date ? data.created.toISOString().split('T')[0] : data.created;
const updated = data.updated instanceof Date ? data.updated.toISOString().split('T')[0] : data.updated;
const meta: PageMeta = {
title: data.title,
type: data.type as 'entity' | 'concept' | 'source',
tags: data.tags as string[],
created,
updated,
filePath,
outgoingLinks: [],
};
if (data.sources !== undefined) {
if (Array.isArray(data.sources)) {
meta.sources = data.sources as string[];
}
}
if (typeof data.author === 'string') {
meta.author = data.author;
}
if (data.date !== undefined) {
if (data.date instanceof Date) {
meta.date = data.date.toISOString().split('T')[0];
} else if (typeof data.date === 'string') {
meta.date = data.date;
}
}
if (typeof data.url === 'string') {
meta.url = data.url;
}
return { success: true, meta };
}