docs/lib/read-frontmatter.js

76 строки
2.2 KiB
JavaScript

const matter = require('gray-matter')
const revalidator = require('revalidator')
const { difference, intersection } = require('lodash')
function readFrontmatter (markdown, opts = { validateKeyNames: false, validateKeyOrder: false }) {
const schema = opts.schema || { properties: {} }
const filepath = opts.filepath || null
let content, data
let errors = []
try {
({ content, data } = matter(markdown))
} catch (e) {
const defaultReason = 'invalid frontmatter entry'
const reason = e.reason
// make this common error message a little easier to understand
? e.reason.startsWith('can not read a block mapping entry;') ? defaultReason : e.reason
: defaultReason
const error = {
reason,
message: 'YML parsing error!'
}
if (filepath) error.filepath = filepath
errors.push(error)
return { errors }
}
const allowedKeys = Object.keys(schema.properties)
const existingKeys = Object.keys(data)
const expectedKeys = intersection(allowedKeys, existingKeys)
;({ errors } = revalidator.validate(data, schema))
// add filepath property to each error object
if (errors.length && filepath) {
errors = errors.map(error => Object.assign(error, { filepath }))
}
// validate key names
if (opts.validateKeyNames) {
const invalidKeys = difference(existingKeys, allowedKeys)
invalidKeys.forEach(key => {
const error = {
property: key,
message: `not allowed. Allowed properties are: ${allowedKeys.join(', ')}`
}
if (filepath) error.filepath = filepath
errors.push(error)
})
}
// validate key order
if (opts.validateKeyOrder && existingKeys.join('') !== expectedKeys.join('')) {
const error = {
property: 'keys',
message: `keys must be in order. Current: ${existingKeys.join(',')}; Expected: ${expectedKeys.join(',')}`
}
if (filepath) error.filepath = filepath
errors.push(error)
}
return { content, data, errors }
}
// Expose gray-matter's underlying stringify method for joining a parsed
// frontmatter object and a markdown string back into a unified string
//
// stringify('some string', {some: 'frontmatter'})
readFrontmatter.stringify = matter.stringify
module.exports = readFrontmatter