-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
136 lines (125 loc) · 3.02 KB
/
index.js
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
/* eslint-disable no-new-func */
/**
* Parse a file that contains FrontMeta
*
* @param {string} frontmeta the FontMeta
* @returns an object containing 'meta' and 'body' fields
*/
export function parse (frontmeta = '') {
const meta = {}
let body = ''
let matches = []
let match = ''
let state = 0
let dashes = 0
let noMeta = false
let isMeta = false
let isBody = false
let key = ''
let value = ''
const lexer = /-|:|\r\n|\n|\r|\s|[^:\s\r\n]+/y
while ((matches = lexer.exec(frontmeta)) !== null) {
match = matches[0]
switch (state) {
case 0: // start of the file
switch (true) {
case match === '-':
dashes++
state = 1
break
case /^(\s)$/.test(match):
state = 0
break
default:
noMeta = true
break
}
break
case 1: // dash marker
switch (true) {
case match === '-':
dashes++
state = 1
break
case /^(\r\n|\n|\r)$/.test(match):
if (dashes < 3) {
throw Error('ERR: Meta boundary must have at least 3 dashes')
}
if (!isMeta) {
isMeta = true
state = 2
} else {
isBody = true
state = 5
}
dashes = 0
break
default:
break
}
break
case 2: // meta-key
switch (true) {
case match === ':':
state = 3
break
case /^(\s)$/.test(match):
state = 2
break
case /^(\r\n|\n|\r)$/.test(match):
throw Error('ERR: Broken key:value pair')
default:
key += match
state = 2
break
}
break
case 3: // meta-value
switch (true) {
case (value === '' && /^(\s)$/.test(match)):
state = 3
break
case /^(\r\n|\n|\r)$/.test(match):
state = 1
meta[key] = value.trimRight()
key = ''
value = ''
break
default:
state = 3
value += match
break
}
break
}
if (noMeta) {
body = frontmeta
break
}
if (isBody) {
body = frontmeta.substr(lexer.lastIndex, frontmeta.length - 1)
break
}
}
return { meta, body }
}
/**
* Stringify takes a FrontMeta document object and returns FrontMatter
*
* @param {Object} document a FrontMeta document object
* @returns {string} the FrontMeta string
*/
export function stringify (document) {
if (!document.meta || Object.keys(document.meta).length === 0) { return document.body }
let output = '---\n'
const metaKeys = Object.keys(document.meta)
metaKeys.forEach((key) => {
output += `${key}: ${document.meta[key]}\n`
})
output += '---\n'
if (document.body) {
output += document.body
}
return output
}
export default { parse, stringify }